简易selenium自动化测试框架(Python)
最近空闲时间在探索Selenium的自动化测试,简单的写了一个小框架来测试公司的一个web产品。该框架包括以下模块:
1. Test case编写模式(page模式,参考之前的博文http://www.cnblogs.com/AlwinXu/p/5537955.html)
2. Test case的管理及执行 (主要是用nose)
该模块借助了一个外部txt文件来记录测试用例,每个用例为自身的文件名,如果不需要在本次执行,只需在文件名前添加一个“#”标识符就可以跳过该用例的执行。
3. 测试报告的生成(xml和html两种格式)
对于自动化测试而言,这些模块应该是最基本的配置了,当然还有一些辅助模块比如日志,其他公共库模块等需要根据具体的业务逐渐丰富。闲话少说,用代码交流吧。
测试用例编写
该模块用了Page模式,之前介绍过,这次只贴代码了
BasePage.py:
__author__ = 'xua' #super class
class BasePage(object):
def __init__(self, driver):
self.driver = driver
然后是各个web page继承BasePage,LoginPage.py:
from BasePage import BasePage
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys class LoginPage(BasePage):
"""description of class""" #page element identifier
usename = (By.ID,'username')
password = (By.ID, 'password')
dialogTitle = (By.XPATH,'//html/body/div[7]/div/div/div[1]/h3')
cancelButton = (By.XPATH,'//html/body/div[7]/div/div/div[3]/button[2]') #Get username textbox and input username
def set_username(self,username):
name = self.driver.find_element(*LoginPage.usename)
name.send_keys(username) #Get password textbox and input password, then hit return
def set_password(self, password):
pwd = self.driver.find_element(*LoginPage.password)
pwd.send_keys(password + Keys.RETURN) #Get pop up dialog title
def get_DiaglogTitle(self):
digTitle = self.driver.find_element(*LoginPage.dialogTitle)
return digTitle.text #Get "cancel" button and then click
def click_cancel(self):
cancelbtn = self.driver.find_element(*LoginPage.cancelButton)
cancelbtn.click()
测试用例信息类:
TestCaseInfo.py
class TestCaseInfo(object):
"""description of class""" def __init__(self, id="",name="",owner="",result="Failed",starttime="",endtime="",errorinfo=""):
self.id = id
self.name = name
self.owner = owner
self.result = result
self.starttime = starttime
self.endtime = endtime
self.errorinfo = errorinfo
最后是每个测试用例的编写:(每个用例必须有自己的用例信息,这里有ID,Name等等信息,也会调用测试结果报告生成模块来添加测试结果)
Test_Login.py
__author__ = 'xua' from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.alert import Alert
import unittest
import time
from LoginPage import LoginPage
from TestCaseInfo import TestCaseInfo
from TestReport import TestReport class Test_Login(unittest.TestCase): #Setup
def setUp(self):
self.driver = webdriver.Chrome(r'C:\Users\xua\Downloads\chromedriver_win32\chromedriver.exe')
self.driver.implicitly_wait(30)
self.base_url = "http://10.222.30.145:9000/"
#test case information
self.testcaseinfo = TestCaseInfo(id="",name="Login to floor manager lite using sbxadmin",owner="xua")
self.testResult = TestReport() def test_Login(self):
try:
self.testcaseinfo.starttime = str(time.asctime())
#Step1: open base site
self.driver.get(self.base_url)
#Step2: Open Login page
login_page = LoginPage(self.driver)
#Step3: Enter username
login_page.set_username("sbXadmin")
#Step4: Enter password
login_page.set_password("IGTtest1")
#Checkpoint1: Check popup dialog title
self.assertEqual(login_page.get_DiaglogTitle(),"Sign in","Not Equal")
#Step5: Cancel dialog
login_page.click_cancel()
self.testcaseinfo.result = "Pass"
except Exception as err:
self.testcaseinfo.errorinfo = str(err)
finally:
self.testcaseinfo.endtime = str(time.asctime()) #tearDown
def tearDown(self):
self.driver.close()
#write test result
self.testResult.WriteHTML(self.testcaseinfo) if __name__ == "__main__":
unittest.main()
用例执行模块
1. 借助外部文件记录需要执行的用例
testcases.txt(带“#”标识的用例不会被执行):
Test_Login.py
Test_Login_2.py
#Test_Login_3.py
Test_Login_4.py
2. 利用nose的nosetests命令执行各个用例:
import subprocess class RunTests(object):
"""description of class"""
def __init__(self):
self.testcaselistfile = "testcases.txt" #use nosetests command to execute test case list
def LoadAndRunTestCases(self):
f = open(self.testcaselistfile)
testfiles = [test for test in f.readlines() if not test.startswith("#")]
f.close()
for item in testfiles:
subprocess.call("nosetests "+str(item).replace("\\n",""),shell = True) if __name__ == "__main__":
newrun = RunTests()
newrun.LoadAndRunTestCases()
测试结果报表生成模块
测试报表模块写了两种格式:xml和html
TestReport.py
from xml.etree import ElementTree as ET
import os
import lxml.etree as mytree
from lxml import html class TestReport(object):
"""description of class"""
def __init__(self):
self.testreport = "TestResult.xml" #If there is no "TestResult.xml", then create one
def CreateTestResultFile(self):
if os.path.exists(self.testreport) == False:
newElem = ET.Element("TestCases")
newTree = ET.ElementTree(newElem)
newTree.write(self.testreport) #Write test result to xml
def WriteResult(self,testcaseInfo):
self.CreateTestResultFile()
testResultFile = ET.parse(self.testreport)
root = testResultFile.getroot()
newElem = ET.Element("TestCase")
newElem.attrib = {
"ID":testcaseInfo.id,
"Name":testcaseInfo.name,
"Owner":testcaseInfo.owner,
"Result":testcaseInfo.result,
"StartTime":testcaseInfo.starttime,
"EndTime":testcaseInfo.endtime,
"ErrorInfo":testcaseInfo.errorinfo
}
root.append(newElem) testResultFile.write(self.testreport) #If there is no "TestResult.html" file exists, then create one with default style
def CreateHtmlFile(self):
if os.path.exists("TestResult.html") == False:
f = open("TestResult.html",'w')
message = """<html>
<head>
<title>Automation Test Result</title>
<style>
table {
border-collapse: collapse;
padding: 15px;
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
}
th{
background-color: green;
color: white;
border: 1px solid #ddd;
padding-bottom: 15px;
padding-top: 15px;
}
tr{
border: 1px solid #008000;
padding-bottom: 8px;
padding-top: 8px;
text-align: left;
}
td{
border: 1px solid #008000;
}
</style>
</head>
<body>
<h1>Automation Test Result</h1>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Owner</th>
<th>Result</th>
<th>StartTime</th>
<th>EndTime</th>
<th>ErrorMessage</th>
</tr>
</table>
</body>
</html>
"""
f.write(message)
f.close() #append new test result to testresult file
def WriteHTML(self,testcaseinfo): self.CreateHtmlFile() f = open("TestResult.html","r") htmlcontent = f.read()
f.close()
tree = html.fromstring(htmlcontent)
tableElem = tree.find(".//table")
if testcaseinfo.result == "Failed":
mytablerow = "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td bgcolor=\"#FF0000\">{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>".format(testcaseinfo.id,testcaseinfo.name,testcaseinfo.owner,testcaseinfo.result,testcaseinfo.starttime,testcaseinfo.endtime,testcaseinfo.errorinfo)
else:
mytablerow = "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>".format(testcaseinfo.id,testcaseinfo.name,testcaseinfo.owner,testcaseinfo.result,testcaseinfo.starttime,testcaseinfo.endtime,testcaseinfo.errorinfo)
tableElem.append(mytree.HTML(str(mytablerow))) f = open("TestResult.html","w")
#html.tostring
newContent = repr(html.tostring(tree,method="html",with_tail=False))
newContent = newContent.replace(r"\n","").replace(r"\t","").replace('b\'',"")
newContent = newContent[:len(newContent)-1]
f.write(newContent)
f.close()
ok,最后看一下生成的测试报表:
总结
在网上有很多关于Selenium自动化的Best Practice,当然大家也可以根据自己的需求来DIY自己的框架,不管简陋与否,好用才是硬道理:)!
简易selenium自动化测试框架(Python)的更多相关文章
- 《Selenium自动化测试实战:基于Python》Selenium自动化测试框架入门
第1章 Selenium自动化测试框架入门 1.1 Selenium自动化测试框架概述 说到目前流行的自动化测试工具,相信只要做过软件测试相关工作,就一定听说过Selenium. 图1-1是某企业 ...
- Selenium自动化测试框架入门整理
关注嘉为科技,获取运维新知 本文主要针对Selenium自动化测试框架入门整理,只涉及总体功能及框架要点介绍说明,以及使用前提技术基础要求整理说明.作为开发人员.测试人员入门参考. 本文参考:Se ...
- PO模式在selenium自动化测试框架有什么好处
PO模式是在UI自动化测试过程当中使用非常频繁的一种设计模式,使用这种模式后,可以有效的提升代码的复用能力,并且让自动化测试代码维护起来更加方便. PO模式的全称叫page object model( ...
- 《手把手教你》系列基础篇(八十)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试-番外篇(详解教程)
1.简介 经过前边几篇知识点的介绍,今天宏哥就在实际测试中应用一下前边所学的依赖测试.这一篇主要介绍在TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用de ...
- Selenium自动化测试框架介绍
Selenium自动化测试框架介绍 1.测试架构作用 a.可维护性 b.提高编写脚本效率 c.提高脚本的可读性 2.框架的几大要素: Driver管理,脚本,数据,元素对象,LOG,报告,运行机制,失 ...
- Python3简易接口自动化测试框架设计与实现(中)
目录 7.Excel数据读取 7.1.读取配置文件 7.1.编写Excel操作类 8.用例组装 9.用例运行结果校验 10.运行用例 11 .小结 上一篇:Python3简易接口自动化测试框架设计与实 ...
- 《手把手教你》系列基础篇(七十五)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 中篇(详解教程)
1.简介 上一篇中介绍了DataProvider如何传递参数,以及和一些其他方法结合传递参数,今天宏哥接着把剩下的一些常用的也做一下简单的介绍和分享. 2.项目实战1 @DataProvider + ...
- 《手把手教你》系列基础篇(七十六)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 下篇(详解教程)
1.简介 今天这一篇宏哥主要是结合实际工作中将遇到的测试场景和前边两篇学习的知识结合起来给大家讲解和分享一下,希望以后大家在以后遇到其他的测试场景也可以将自己的所学的知识应用到测试场景中. 2.测试场 ...
- 《手把手教你》系列基础篇(七十七)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 上篇(详解教程)
1.简介 今天主要是讲解和分享:TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用dependsOnMethods,testNG会自动根据@Test方法名称 ...
随机推荐
- Qt_颜色选择对话框(QColorDialog)
转自豆子空间 使用QColorDialog也很简单,Qt提供了getColor()函数,类似于QFileDialog的getOpenFileName(),可以直接获得选择的颜色. include &l ...
- Jquery 组 标签页
<!DOCTYPE html><html lang="zh-cn"><head> <meta charset="utf-8&qu ...
- String()与toString的区别
1..toString()可以将所有的的数据都转换为字符串,但是要排除null 和 undefined 代码示例: var a = null.toString()--报错 var b = underf ...
- JavaScript高级程序设计 第六章 面向对象程序设计
面向对象程序设计 ECMA-262将对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.”严格来讲,这就相当于说对象是一组没有特定顺序的值.对象的每个属性和方法都有一个名字,而每个名字都 ...
- link & auto cards
link & auto cards a link to card link https://docs.embed.ly/docs/cards DD WX <blockquote clas ...
- Lodop窗口的按钮、权限,隐藏或设置功能不可用
Lodop隐藏某个按钮或部分,具体参考Lodop技术手册 SET_SHOW_MODE篇.以下是几个例子,(对应下图图片): 第一种:LODOP.SET_SHOW_MODE ("HIDE_PB ...
- BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)
题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...
- iOS 【终极方案】精准获取webView内容高度,自适应高度
前言:是这样的,刚写完上一篇文章还没缓过神来,上一篇文章我还提到了,想和大家聊聊原生+H5如何无缝连接的故事.结果我朋友就给我发了两篇他的作品.他的做法也都有独到之处.好的文章都是这样,让你每次看都能 ...
- 洛谷 P3253 [JLOI2013]删除物品 解题报告
P3253 [JLOI2013]删除物品 题目描述 箱子再分配问题需要解决如下问题: (1)一共有\(N\)个物品,堆成\(M\)堆. (2)所有物品都是一样的,但是它们有不同的优先级. (3)你只能 ...
- android 混淆 与 反编译
1, 文件 project.properties 修改: target=android-14proguard.config=${sdk.dir}/tools/proguard/proguard-and ...