定义:是Python自带的一个单元测试框架,存放在Python安装目录的lib目录下
unittest的四个核心概念:
①测试用例 test case
②测试夹具 test fixture
③测试执行 test runner
④测试套件 test suite
1.test case测试用例书写规则
①.py文件名 必须是以test开头
②测试类 必须继承父类 unittest.TestCase
③测试类名必须以Test开头
④测试方法最好以test开头
⑤在当前测试文件执行测试代码时,使用: unittest.main()
if __name__ == '__main__': unittest.main()
⑥在测试类里可以有普通的方法,但是普通方法需要被测试方法调用
书写语法(如下):
# 导包
import unittest
class Testcase(unittest.TestCase):
def test_01(self):
print('测试方法的书写规则111')
def test_02(self):
print('测试方法的书写规则222')
#执行unittest的测试代码 使用unittest.main()
if __name__ == '__main__':
unittest.main()
2.test fixture 测试夹具
2.1方法级别的测试夹具:
setup() ---> 在每一个测试方法执行前 先执行的setup()的代码
teardown()---在每一个测试方法执行后 先执行的teardown()的代码
方法级别的夹具如:
#方法级别的测试夹具
# 导包
import unittest
class Testcase(unittest.TestCase):
def test_01(self):
print('测试方法的书写规则111')
def test_02(self):
print('测试方法的书写规则222')
#测试夹具--->方法级别
def setUp(self) -> None:
print('方法级别的夹具执行在方法前')
def tearDown(self) -> None:
print('方法级别的夹具执行在方法后')
#执行unittest的测试代码 使用unittest.main()
if __name__ == '__main__':
unittest.main()
运行结果
2.2类级别的测试夹具
setupClass()--->在执行类之前 执行夹具,需要@classmethod装饰
teardownClass()--->在执行类之后 执行夹具,需要@classmethod装饰
类级别的夹具如:
#类级别的测试夹具
# 导包
import unittest
class Testcase(unittest.TestCase):
def test_01(self):
print('测试方法的书写规则111')
def test_02(self):
print('测试方法的书写规则222')
#测试夹具--->类级别
@classmethod
def setUpClass(cls) -> None:
print('类级别的夹具执行在类前')
@classmethod
def tearDownClass(cls) -> None:
print('类级别的夹具执行在类后')
#执行unittest的测试代码 使用unittest.main()
if __name__ == '__main__':
unittest.main()
运行结果
3 .test runner 测试执行 和 test suite 测试套件
注意:在执行用例顺序中,默认按ASCII码顺序执行,所有建议方法名创建是后面可以加上序号,如:test_01(self):
测试套件:把需要执行的测试用例 放到一个套子
测试执行:使用测试执行去执行套子里的用例
测试执行和测试套件基本都是组合使用
语法
3.1 组合方式① (执行一条或多条用例)
语法:
①导包(新创建的.py文件)
import unittest
from 测试包名.测试用例模块名 import 测试用例类名
②套件
suite=unittest.TestSuite()
suite.addTest(测试类名("测试方法1字符串"))
suite.addTest(测试类名("测试方法2字符串"))
.....
③测试执行
runner=unittest.TextTestRunner()
runner.run(suite)
3.2组合方式②(添加所有测试用例套件)
语法:
①导包
import unittest
②添加所有测试套件
suite=unittest.defaultTestLoader.discover(start_dir,pattern)
start_dir:测试用例的路径目录名
pattern:选取测试用例执行的规则
③执行用例
runner=unittest.TextTest()
runner.run(suite)
4.断言
定义:常用在unittest中 , 判断预期结果和实际结果是否相符合, 一般断言都在测试方法中被调用
三种断言方法:
①self.assertEqual(a,b,msg='测试失败时打印的信息')
断言a和b是否相等,相等则测试用例通过
②assertTrue(x,msg='测试失败时打印的信息')
断言x是否True,是True则测试用例通过
③assertIn(a,b,msg='测试失败时打印的信息')
断言a是否在b中,在b中则测试用例通过
断言示例:
# 导包
import unittest
class Testcase(unittest.TestCase):
def test_01(self):
print('测试方法的书写规则111')
self.assertEqual(1, 1, msg='测试失败')
def test_02(self):
print('测试方法的书写规则222')
self.assertTrue(1==2, msg="测试失败")
def test_03(self):
print('测试方法的书写规则333')
self.assertIn("1","123" , msg="测试失败")
#执行unittest的测试代码 使用unittest.main()
if __name__ == '__main__':
unittest.main()
执行结果:
5.跳过测试
直接跳过该测试方法(用例),不去执行它
常用的跳过测试方法/装饰器
@unittest.skip(reason):skip(reason)装饰器,无条件跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipIf(reason):skipIf(condition,reason)装饰器,条件为真时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipUnless(reason):skipUnless(condition,reason)装饰器,条件为假时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.expectedFailure:测试标记为失败。
示例:
# 导包
import unittest
class Testcase(unittest.TestCase):
def test_01(self):
print('测试方法的书写规则111')
def test_02(self):
print('测试方法的书写规则222')
def test_03(self):
print('测试方法的书写规则333')
#跳过测试06-08
@unittest.skip('没原因直接跳这条用例')
def test_06jump(self):
print('跳过测试1')
@unittest.skipIf(1==1,"表达式为真,跳过这条用例")
def test_07jump(self):
print ('跳过测试2')
@unittest.skipUnless(1==2,'表达式为假,跳过这条用例')
def test_08jump(self):
print ('跳过测试3')
#执行unittest的测试代码 使用unittest.main()
if __name__ == '__main__':
unittest.main()
执行结果:
6.HTMLTestRunner 第三方插件
注意:1.生成的报告应该放在Report里面 2.生成的报告应该以 .html结尾
示例:
# 报告的编写需要先导包
import unittest
import HTMLTestRunnerPlugins
import time
import os
# 实例化一个套件,传入测试类所在的目录 ,
suite=unittest.defaultTestLoader.discover("../Case",pattern="test*")
#实例话一个时间格式化
timename=time.strftime("%Y-%m-%d %H_%M_%S") #放在HTML文件名前,成为文件名的一部分 这样文件名不会重复 ,但是格式必须是下划线或横线 不能是冒号: 否则会报错
#需要把HTML文件放到report ,所以HTML的路径必然是在report中---->导入os包
caseHTML_path=os.path.dirname(__file__) #获取当前目录
filename=caseHTML_path+'/'+timename+'filename.HTML'
with open(filename,"wb") as fq:
#实例化一个HTMLTestRunner
runner=HTMLTestRunnerPlugins.HTMLTestRunner(
stream=fq,
verbosity=2,
title="测试报告标题",
description="描述",
tester="测试者"
)
runner.run(suite)
7.数据驱动
防止写重复的代码,有的用例只是参数不一样,其他代码完全一样,就可以通过在unittest里面需要使用 ddt 来提供参数化的功能
使用:
ddt可以参数化读取列表嵌套列表或者列表嵌套字典的数据
①列表嵌套列表读取:
先在类前面加上: @ddt.ddt
在方法前面加上: @ddt.data(*列表嵌套列表)
@ddt.unpack
②列表嵌套字典读取:
先在类前面加上: @ddt.ddt
在方法前面加上: @ddt.data(*列表嵌套字典) 在方法里面使用一个形式参数来接收