Python为开发者提供了内置的单元测试框架 unittest,它是一种强大的工具,能够有效地编写和执行单元测试。unittest 提供了完整的测试结构,支持自动化测试的执行,能够对测试用例进行组织,并且提供了丰富的断言方法。最终,unittest 会生成详细的测试报告,这个框架非常简单且易于使用。
unittest核心概念
在 unittest 中,有几个核心概念:
- TestCase(测试用例):每个测试用例实例用于封装一个或多个测试函数。
- TestSuite(测试套件):这是多个测试用例的集合,用于组织和执行多个测试用例。
- TestLoader(测试加载器):这是一个用于将测试用例加载到测试套件中的工具。
- TextTestRunner(测试运行器):这是用于执行测试用例的运行器,负责运行测试并生成结果报告。
- Fixture(环境管理机制):这是测试用例的环境搭建和销毁部分,包括前置条件和后置条件。
unittest的工作流程
- 编写继承自 unittest.TestCase 的测试用例类,其中每个测试函数都是一个独立的测试用例。
- 使用 TestLoader 加载测试用例,并将它们组织成 TestSuite 对象。
- 使用 TestRunner 运行 TestSuite 中的测试用例,并输出测试结果。
使用unittest初级指南
- 导入 unittest 模块以及被测试的文件或类。
- 创建一个测试类,并继承 unittest.TestCase,所有自定义的单元测试类都要继承它,作为基类。
- 重写 setUp 和 tearDown 方法,用于初始化和清理测试环境(如果有必要)。
- 定义测试函数,函数名以 test_ 开头,这样才能被识别并执行。
- 在测试函数中使用断言来判断测试结果是否符合预期。
- 调用 unittest.main() 方法运行测试用例,按照函数名的排序执行测试。
以下是一个简单的例子:
以上是一个简单的测试用例,包含了两个测试函数。运行脚本将输出测试结果。
unittest核心概念
测试脚手架
测试脚手架 是测试用例的前置条件和后置条件,确保测试环境的初始化和清理,从而保证测试的准确性和可靠性。
- setUp():每个测试方法运行前执行,用于测试前置的初始化工作。
- tearDown():每个测试方法结束后执行,用于测试后的清理工作。
- setUpClass():所有的测试方法运行前执行,用于单元测试类运行前的准备工作。使用 @classmethod 装饰器装饰,整个测试类运行过程中只会执行一次。
- tearDownClass():所有的测试方法结束后执行,用于单元测试类运行后的清理工作。使用 @classmethod 装饰器装饰,整个测试类运行过程中只会执行一次。
测试用例
测试用例 是最小的测试单元,用于检测特定的输入集合的特定的返回值。unittest 提供了 TestCase 基类,所有的测试类都需要继承该基类,而在该类下的函数如果以 test_ 开头,则被标识为测试函数:
断言方法
以下是常用的断言方法:
- assertEqual(a, b, msg=None):验证 a 等于 b。
- assertNotEqual(a, b):验证 a 不等于 b。
- assertTrue(x):验证 x 是否为 True。
- assertFalse(x):验证 x 是否为 False。
- assertIs(a, b):验证 a 是否是 b。
- assertIsNot(a, b):验证 a 是否不是 b。
- assertIsNone(x):验证 x 是否为 None。
- assertIsNotNone(x):验证 x 是否不为 None。
- assertIn(a, b):验证 a 是否在 b 中。
- assertNotIn(a, b):验证 a 是否不在 b 中。
- assertIsInstance(a, b):验证 a 是否是 b 类型的实例。
- assertNotIsInstance(a, b):验证 a 是否不是 b 类型的实例。
可以使用这些方法进行断言,也可以直接使用原生的assert来断言,如果断言失败,测试用例会被定义为执行失败。
忽略特定测试方法
unittest 提供了一些方法来跳过特定的测试用例:
- @unittest.skip(reason):强制跳过,reason 是跳过的原因。
- @unittest.skipIf(condition, reason):当 condition 为 True 时跳过。
- @unittest.skipUnless(condition, reason):当 condition 为 False 时跳过。
- @unittest.expectedFailure:如果测试失败,这个测试用例不会计入失败的统计。
使用实例方法:self.skipTest() 使用和上述类似。
测试套件
测试套件用于收集和组织多个测试用例,便于集中执行。
- 通过 unittest.main() 方法直接加载单元测试的测试模块,这是一种简单的加载方式。所有测试用例的执行顺序按照方法名的字符串表示的 ASCII 码升序排序,通过命名时使用 test_01_xxx 来指定执行顺序。
- 将所有的单元测试用例 TestCase 加载到测试套件 Test Suite 集合中,然后一次性加载所有测试对象。
通过 TestSuite 对象收集
此方式适用于需要自定义组合特定测试用例的情况。
通过 TestLoader 对象收集
TestLoader 是 unittest 框架提供的加载测试用例的类。
测试运行器
测试运行器是用于执行和输出测试结果的组件。常用的运行器有:
- unittest.TextTestRunner:这是 unittest 框架中默认的测试运行器,会在命令行输出测试结果。通过调用 run() 方法运行测试套件,并将测试结果打印到控制台。
- HTMLTestRunner:这是一个第三方库,能够生成漂亮的 HTML 测试报告,需要进行安装。你可以通过搜索获取相关文件进行安装。
- XMLTestRunner:这是另一个第三方库,用于生成 XML 格式的测试报告。
你也可以自定义测试运行器。继承 unittest.TestRunner 类并实现 run() 方法,以创建自己的测试运行器。
通常使用 HTMLTestRunner 即可满足需求,它非常易用。
实战一个测试案例
假设有一个测试函数 login:
设计用例
根据函数的参数和逻辑,设计如下用例:
编写测试用例并运行
这是一个简单的测试用例,包含了三个测试函数。运行测试用例后,会输出测试结果,看完是否觉得unittest非常简单易用。ner.run(suite)