近期更新完毕,建议关注收藏!
目录
- 简介
- TestCase
- TestSuite
- TestRunner
- TestLoader
- Fixture
- 断言
- 参数化
- 跳过
- 生成报告
tips:ctrl+? 可以看方法的help文档
简介
python自带的单元测试框架,也可以做自动化测试
组织多个用例去执行,用例都是用单独的目录存放的
丰富断言方法
可生成测试报告
核心要素为下方5个标题
TestCase
测试用例,用来书写用例代码
可以执行单个测试用例
- 命名要满足规则
不能出现中文
test_项目_模块_功能.py - 当文件中先进行其他python操作时很可能不能识别成测试文件,解决方法如下
- 终端信息
一个点代表一个用例通过,出现S表示跳过。上述图中4个.表示4个用例通过
import unittest# 定义测试类 继承unittest.TestCase类
class TestDemo(unittest.TestCase):#测试方法的命名必须以test开头def test_method1(self):passdef test_method2(self):pass#执行 1.在类名或方法名后面右键运行 右键后的按钮出现unittest....就是识别到了
#如果没有识别到,检查命名、新建一个文件重试或采用第二点执行方法
# 2.在主程序中使用unittest.main()执行
if __name__=='__main__':unittest.main()
TestSuite
测试套件,用来打包TestCase
import unittest
#允许导入测试用例文件
from testcase1 import TestDemo1#实例化套件对象
suite=unittest.TestSuite()
#添加用例方法
suite.addTest(ClassName("MethodName"))
#批量添加测试方法 套件对象.addTest(unittest.makeSuite(测试类名))
suite.addTest(unittest.makeSuite(TestDemo1))
#添加扩展
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ClassName))#把指定的类中测试用例全部添加到测试套件中
TestRunner
测试执行,运行TestSuite
import unittest
from testcase1 import TestDemo1
from testcase2 import TestDemo2
suite=unittest.TestSuite()
suite.addTest(TestDemo1("test_method1"))
suite.addTest(TestDemo1("test_method2"))
suite.addTest(TestDemo2("test_method1"))
suite.addTest(TestDemo2("test_method2"))
#批量添加
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))#实例化执行对象 unittest.TextTestRunner()
runner=unittest.TextTestRunner()
#执行套件对象: 执行对象.run(套件对象)
runner.run(suite)
TestLoader
测试加载,对测试套件功能的补充
作用和TestSuite一样,组装用例代码,也需要TextTestRunner()执行
- 为什么还需要这个?很多Suite写法在多个用例的情况下过于复杂, TestLoader进行简化,管理多个Test Case
#实例化加载对象并加载用例,得到套件对象
#suite=unittest.TestLoader().discover('用例所在目录','用例代码文件名.py')
suite=unittest.TestLoader().discover('.','test02*.py')#实例化执行对象并执行
runner=unittest.TextTestRunner().run(suite)
Fixture
测试夹具,一种代码结构,书写前置方法(执行用例之前)和后置方法(用例之后);由此可得执行顺序为前置->用例->后置;省略了重复步骤的代码。
分为 方法级别、类级别、模块级别
方法级别在每个用例执行前后都会自动调用,方法名固定
类级别在类汇总所有测试方法执行前后自动调用,一个类别只执行一次
模块级别就是代码文件级别,整个代码文件执行前后执行一次
可以不成对出现
def setUp(self): #前置#每个用例执行前都会调用pass
def tearDown(self):#后置#每个用例执行后都会调用pass#类级别需要转换成类方法
@classmethod
def setUpClass(cls): #前置pass
@classmethod
def tearDownClass(cls):#后置pass#模块文件级别
#类外部定义
def setUpModule(): #前置pass
def tearDownModule():#后置pass
- 如果打印中显示先做了类级别的前置和后置,然后再做了其他,实际上运行还是按正常顺序的,正常情况。
断言
断言方法 | 描述 | 示例代码 |
---|---|---|
assertEqual(a, b) | 判断 a 是否等于 b ,不等则失败 | self.assertEqual(2 + 2, 4) |
assertNotEqual(a, b) | 判断 a 是否不等于 b ,相等则失败 | self.assertNotEqual(2 + 2, 5) |
assertTrue(x) | 判断 x 是否为 True ,否则失败 | self.assertTrue(1 + 1 == 2) |
assertFalse(x) | 判断 x 是否为 False ,否则失败 | self.assertFalse(1 + 1 == 3) |
assertIs(a, b) | 判断 a 和 b 是否是同一个对象 | self.assertIs(a, b) |
assertIsNot(a, b) | 判断 a 和 b 是否不是同一个对象 | self.assertIsNot(a, b) |
assertIsNone(x) | 判断 x 是否为 None ,否则失败 | self.assertIsNone(None) |
assertIsNotNone(x) | 判断 x 是否不是 None ,否则失败 | self.assertIsNotNone(5) |
assertIn(a, b) | 判断 a 是否在 b 中(如列表、字符串等容器) | self.assertIn(3, [1, 2, 3]) |
assertNotIn(a, b) | 判断 a 是否不在 b 中 | self.assertNotIn(4, [1, 2, 3]) |
assertRaises(exception, callable, *args, **kwargs) | 判断 callable 是否抛出指定异常 exception | with self.assertRaises(ValueError): int("not a number") |
assertAlmostEqual(a, b, places=7) | 判断 a 和 b 是否相等,允许在小数点后 places 位数上有微小误差 | self.assertAlmostEqual(1.234567, 1.234568, places=5) |
assertNotAlmostEqual(a, b, places=7) | 判断 a 和 b 是否不相等,允许在小数点后 places 位数上有微小误差 | self.assertNotAlmostEqual(1.234567, 1.234568, places=5) |
如何使用?self.assert…()调用
失败会出现FAILED,最上面会显示通过几项
参数化
批量输入不同的用例,重复执行多次
- unittest本身不支持参数化,但可以通过安装扩展插件parameterized来实现
pip install parameterized
import unittest
import parameterized
from tools import add
#测试数据用变量expect表示
#组织测试数据,用列表中包括元组,一个元组就是一组测试数据
data=[(1,1,2),(2,3,5),...]class TestAdd(unittest.TestCase):@parameterized.expand(data)
#参数化,在测试方法上方使用装饰器@parameterized.expand(测试数据)def test_add(self,a,b,expect):self.assertEqual(expect,add(a,b))
#运行 或者右键运行 或放到Suite运行
if __name__=='__main__':unittest.main()
数据也可以存放在.json文件中,读取出来参数化
import json
def read_test_data():with open('add_data.json')as f:data=json.load(f)return data#测试文件中
@parameterized.expand(read_test_data())#数字四舍五入
round(num,2) #2位小数
json文件可以根据数据结构的复杂改变格式
[{"a":1,"b":2,"expect":3}] #复杂形式
[[1,1,2],[2,3,4]]#简单形式
跳过
对于未完成的/不满足测试条件的,先跳过执行
#直接将测试函数标记为跳过
@unittest.skip('skip_reason')
#根据条件判断测试函数是否跳过
@unittest.skipIf(判断条件,reason='skip_reason')#判断条件为真则跳过
生成报告
html测试报告
unittest本身不支持生成html格式的测试报告
这里采用HTMLTestReport类库生成
pip install HTMLTestReport
本质是TestRunner
- 使用
#导包
import unittest
from htmltestreport import HTMLTestReport
from tool import TestAdd#组装用例(套件,loader)
suite= unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAdd))#使用HTMLTestReport中的runner执行套件
runner=HTMLTestReport(filepath,title,description)#描述可选填
#查看报告 首次打开会比较慢
runner.run(suite)#补充:快速获取路径
abspath=os.path.abspath(__file__)#获取当前绝对路径
#__file__当前代码文件名
dirname=os.path.dirname(filepath)#获取其所在的目录地址