目录
框架解析
unittest 是python 的单元测试框架,它主要有以下作用:
- 提供用例组织与执行
- 提供丰富的比较方法
- 提供丰富的日志
unittest里面有四个很重要的概念,test fixture,test case,test suite,test runner。
test fixture(测试固件)
对一个测试用例环境的搭建和销毁,就是一个fixture,通过覆盖setUp()和tearDown()方法来实现。
- setUp():测试环境和数据的准备工作
- tearDown():做测试用例执行完成之后的清理工作
test case(测试用例)
测试用例就是一个完整的测试流程,包括测试前准备环境的搭建(setUp)、实现测试过程的代码,以及测试后环境的还原(tearDown)。一个用例就是一个方法,名字以test_开头。
test suite(测试套件)
一个功能的验证往往需要多个测试用例,可以把多个测试用例集合在一起执行,这个就产生了测试套件TestSuite的概念。必须以继承(面向对象)的方式来使用。
test runner(测试执行)
测试的执行也是非常重要的一个概念,在unittest框架中,通过TextTestRunner类提供的run()方法来执行test suite/test case。
批量执行脚本
构建测试套件
假设我们已经编写好了test1.py与test2.py两个文件,那么我们如何同时执行这两个文件呢?
addTest()
TestSuite类的addTest()方法可以把不同的测试类中的测试方法组装到测试套件中,但是addTest()一次只能把一个类里面的一个测试方法组装到测试套件中。
import unittest
from src0716 import test1
from src0716 import test2
def createsuite():
#addTest
suite = unittest.TestSuite()
suite.addTest(test1.Baidu1("test_hao")) #addTest(脚本名.类名("方法名"))
suite.addTest(test1.Baidu1("test_hbaidu"))
suite.addTest(test2.Baidu2("test_hao"))
suite.addTest(test2.Baidu2("test_baidusearch"))
return suite
if __name__=="__main__":
suite = createsuite()
runner = unittest.TextTestRunner(verbosity=2) #verbosity 0,1,2数字越大后台打印越详细
runner.run(suite)
但是上述做法有两个不方便的地方:
- 需要导入所有的相关的py文件,比如 import test1,每新增一个脚本就需要导入一个。
- addTest一次只能增加一个测试方法,如果一个py文件中有10个测试方式,如果都要组装到测试套件中,就需要增加10次。
makeSuit()
在unittest 框架中提供了makeSuite() 的方法,makeSuite可以实现把测试用例类内所有的测试case组成的测试套件TestSuite ,unittest 调用makeSuite的时候,只需要把测试类名称传入即可。
suite.addTest(unittest.makeSuite(test1.Baidu1))
suite.addTest(unittest.makeSuite(test2.Baidu2))
TestLoader()
TestLoader 用于创建类和模块的测试套件,一般的情况下,用TestLoader().loadTestsFromTestCase(TestClass) 来加载测试类。
suite1 = unittest.TestLoader().loadTestsFromTestCase(test1.Baidu1)
suite2 = unittest.TestLoader().loadTestsFromTestCase(test2.Baidu2)
suite = unittest.TestSuite([suite1, suite2])
但是makeTest()和TestLoader()仍每新增一个脚本就需要导入一个相关的文件。
discover()
discover 是通过递归的方式到其子目录中从指定的目录开始, 找到所有测试模块并返回一个包含它们对象的TestSuite ,然后进行加载与模式匹配唯一的测试文件,也就是把一个文件夹下所有测试脚本的测试用例都执行一遍,discover 参数分别为
unittest.defaultTestLoder.discover("../src",pattern="test*.py",top_level_dir=None) # 文件夹 测试用例所在文件
用例的执行顺序
unittest 框架默认加载测试用例的顺序是根据ASCII 码的顺序,数字与字母的顺序为:0~9,A~Z,a~z 。addTest()是按照添加的顺序来执行。
忽略用例执行
对于不想运行的测试用例打标签:@unittest.skip("skiping")
@unittest.skip("skipping")
def test_baidusearch(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys(u"测试")
driver.find_element_by_id("su").click()
driver.find_element_by_id("su").click()
unittest断言
断言:判断实际结果和预期结果是否相符合
常用的断言:
self.assertEqual(arg1,arg2,msg=" XXX") | 预判表达式arg1与arg2相等,否则输出XXX |
self.assertNotEqual(arg1,arg2,msg="XXX") | 预判表达式arg1与arg2不相等,否则输出XXX |
self.assertTrue(arg1,msg="XXX") | 预判表达式arg1为真,否则输出XXX |
self.assertFalse(arg2,msg="XXX") | 预判表达式arg2为假,否则输出XXX |
HTML报告的生成
运行一个测试套,里面有上百个测试用例,如何集中并且清晰的查看测试用例的执行结果呢?脚本执行完后可以生成HTML报告
HTMLTestRunner.py 文件,并放入python38/Lib目录下,下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
生成HTML报告的步骤:
1.创建一个存放HTML报告的文件夹:
curpath=sys.path[0]
if not os.path.exists(curpath+'/resultreport'):
os.makedirs(curpath+'/resultreport')
2.解决重复命名的问题(用时间来命名):
now=time.strftime("%Y-%m-%d %M %S",time.localtime(time.time()))
filename=curpath+'/resultreport/'+now+'resultreport.html'
3.报告的输出:
异常捕捉与错误截图
错误截图的API:get_screenshot_as_file()
目的:保留测试现场
数据驱动
python 的unittest 没有自带数据驱动功能。所以如果使用unittest,同时又想使用数据驱动,那么就可以使用ddt来完成。ddt的安装
ddt的使用
导包:from ddt import ddt,unpack,data,file_date ;同时在类上面使用标签@ddt
数据驱动的方式:
@data(value) 一次传一个参数
@data(value1,value2....)一次传多个参数,需要用@unpack映射
@file_data("json文件")
@data(*解析数据的方法(txt/csv文件))