常用的python测试框架,推荐使用
pytest。
Test
unittest
内置标准库。支持测试自动化。提供了一系列创建和运行测试的工具。
所有测试文件都必须是可从项目的最高层级目录导入的 模块 或 包。
概念
- test fixture: 测试脚手架,测试所需要进行的准备工作及所有相关的清理操作。
- test case: 测试用例,检查输入特定的数据时的响应。
TestCase类用于新建测试用例。 - test suite: 测试套件,一系列的测试用例,或测试套件,用于归档需要一起执行的测试。
- test runner: 用于执行和输出测试结果的组件。可能使用图形接口、文本接口,或返回一个特定的值表示运行测试的结果。
最佳实践
- 测试方法以
test开头。 - 使用
assertEqual()assertTrue()assertFalse()assertRaises()等来验证结果或异常,以便生成测试报告。 - 使用
setup()tearDown()设置测试开始前与完成后需要执行的指令。 - 测试代码放在单独的模块中,具有测试模块可单独命令行调用,分发时更容易剥离等优点。
1 | import unittest |
命令行接口
1 | 测试整个模块 |
命令行选项
- -v: –verbose, 输出详细测试信息
- -f: –failfast, 出现错误或者失败时,提前停止运行测试
- -s: –start-directory, 开始搜索的目录, 默认当前目录
- -p: –pattern, 正则匹配测试文件名,默认
test*.py
组织测试代码
多个测试运行的顺序由内置字符串排序方法对测试名进行排序的结果决定。
自定义测试子类,这种以 TestCase 测试代码运行的环境被称为 test fixture 。
1 | import unittest |
断言方法:
assertEqual(a, b): a == bassertNotEqual(a, b): a != bassertTrue(x): bool(x) is TrueassertFalse(x): bool(x) is FalseassertIs(a, b): a is bassertIsNot(a, b): a not is bassertIsNone(x): x is NoneassertIsNotNone(x): x is not NoneassertIn(a, b): a in bassertNotIn(a, b): a not in bassertIsInstance(a, b): isinstance(a, b)assertNotIsInstance(a, b): not isinstance(a, b)assertAlmostEqual(a, b): round(a-b, 7) == 0assertNotAlmostEqual(a, b): round(a-b, 7) != 0assertGreater(a, b): a > bassertGreaterEqual(a, b): a >= bassertLess(a, b): a < bassertLessEqual(a, b): a <= bassertRegex(s, r): r.search(s)assertNotRegex(s, r): not r.search(s)assertCountEqual(a, b): 检查每个元素在两个序列中的出现次数是否相同。
assertEqual(a, b) 的默认比较方法,也可自定义:
assertMultiLineEqual(a, b): 比较字符串assertSequenceEqual(a, b): 比较序列assertListEqual(a, b): 比较列表assertTupleEqual(a, b): 比较元组assertSetEqual(a, b): 比较集合assertDictEqual(a, b): 比较字典addTypeEqualityFunc(typeobj, function): 自定义指定类型的比较方法
自定义测试套件:
1 | def suite(): |
复用测试代码
用户有时希望直接使用 unittest 运行已有的测试代码,而不需要把已有的每个测试函数转化为一个 TestCase 的子类。
不推荐,继承 TestCase 的方式会让以后重构测试更加轻松。
1 | def testSomething(): |
跳过测试&预计失败
支持跳过单个或整组的测试用例、支持把测试标注成“预期失败”的测试(会失败但不计入 TestResult 中)。
- @unittest.skip(reason): 跳过被此装饰器装饰的测试。 reason 为跳过原因。
- @unittest.skipIf(condition, reason): condition=True时跳过。
- @unittest.skipUnless(condition, reason): 跳过测试,除非 condition=True
- @unittest.expectedFailure: 将测试标记为预期的失败或错误。发生错误则表示测试成功。
- exception unittest.SkipTest(reason): 引发此异常以跳过一个测试。不推荐直接引发此异常。推荐用以上装饰器。
被跳过的测试的 setUp() 和 tearDown() 不会被运行。被跳过的类的 setUpClass() 和 tearDownClass() 不会被运行。被跳过的模组的 setUpModule() 和 tearDownModule() 不会被运行。
跳过测试方法:
1 | class MyTestCase(unittest.TestCase): |
1 | test_format (__main__.MyTestCase.test_format) ... skipped 'not supported in this library version' |
跳过整个测试类:
1 |
|
表面测试预计会失败:
1 | class ExpectedFailureTestCase(unittest.TestCase): |
循环迭代测试
当几个测试之间的差异非常小,例如只有某些形参不同时,unittest 允许使用 subTest() 上下文管理器在一个测试方法体的内部区分它们。
1 | class NumbersTest(unittest.TestCase): |
pytest
第三方库,语法简洁,插件丰富,要求 python 3.8+ 。
安装
1 | pip install --upgrade pytest |