1. 简介
unittest单元测试框架是受到 JUnit(JAVA) 的启发,与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化,配置共享代码测试。支持将测试样例聚合到测试集中,并将测试与报告框架独立。
2. 构成
静态类图
2.1 fixture
test fixture
表示为了开展一项或多项测试所需要进行的准备工作,以及所有相关的清理操作。举个例子,这可能包含创建临时或代理的数据库、目录,再或者启动一个服务器进程。
- 应用级别为每个测试用例, 在用例
test1 test2 test3
执行前后会分别执行setUp tearDown
方法
import unittest
class TestDemo(unittest.TestCase):
"""Test demo.py"""
def setUp(self):
print("do something before test.Prepare environment.")
def tearDown(self):
print("do something after test.Teardown environment.")
def test1(self):
pass
def test2(self):
pass
def test3(self):
pass
- 应用级别为测试类,在
TestDemo
测试类执行前后分别执行一次setUpClass tearDownClass
即使在这个测试类中有三个测试用例,但是fixture
是 class 级别,所以只执行一次。
- 重写类级别的
fixture
的时候需要使用@classmethod
装饰器
import unittest
class TestDemo(unittest.TestCase):
"""Test demo.py"""
@classmethod
def setUpClass(cls):
print("This setUpClass() method only called once.")
@classmethod
def tearDownClass(cls):
print("This tearDownClass() method only called once too.")
def test1(self):
pass
def test2(self):
pass
def test3(self):
pass
2.2 test case
一个测试用例是一个独立的测试单元。它检查输入特定的数据时的响应。unittest
提供一个基类:TestCase
,用于新建测试用例。
- 编写一个基于
TestCase
的测试类,类名一定要Test
开头,里面的测试用例(类中方法)也是test
开头,这样会被unittest
识别并执行测试。
import unittest
class TestDemo(unittest.TestCase):
"""Test demo.py"""
def test1(self):
"""make some assert"""
self.assertEqual(1 > 2)
def test2(self):
pass
def test3(self):
pass
2.3 test suite
test suite
是一系列的测试用例,或测试套件,或两者皆有。它用于归档需要一起执行的测试。
- 在编写完测试用例后,可以将需要执行测试的用例加入到
test suite
中,以便执行测试 -
suite
中可以嵌套suite
import unittest
class TestDemo(unittest.TestCase):
"""Test demo.py"""
def test1(self):
"""make some assert"""
self.assertEqual(1 > 2)
def test2(self):
pass
def test3(self):
pass
if __name__ == "__main__":
# 创建一个 test suite
suite = unittest.TestSuite()
# 组成一个用例列表
tests = [TestDemo("test1"), TestDemo("test2"), TestDemo("test3")]
# 使用 .addTests 方法将列表中的用例添加至 suite 中
suite.addTests(tests)
# 执行用例
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
2.4 test runner
test runner是一个用于执行和输出测试结果的组件。这个运行器可能使用图形接口、文本接口,或返回一个特定的值表示运行测试的结果。
在上面的代码中已经有使用到 TextTestRunner
- 首先创建一个
runner
对象 - 执行
runner.run()
方法即可执行测试用例,参数为test suite
2.5 assert
- 常规断言方法
| 方法 | 例子 |
| — | — |
|assertEqual(a,b)
| a==b |
|assertNotEqual(a,b)
| a!=b |
|assertTrue(x)
| bool(x)isTrue |
|assertFalse(x)
| bool(x)isFalse |
|assertIs(a,b)
| aisb |
|assertIsNot(a,b)
| aisnotb |
|assertIsNone(x)
| xisNone |
|assertIsNotNone(x)
| xisnotNone |
|assertIn(a,b)
| ainb |
|assertNotIn(a,b)
| anotinb |
|assertIsInstance(a,b)
| isinstance(a,b) |
|assertNotIsInstance(a,b)
| notisinstance(a,b) | - 模糊断言方法
| 方法 | 例子 |
| — | — |
|assertAlmostEqual(a,b)
| round(a-b,7)==0 |
|assertNotAlmostEqual(a,b)
| round(a-b,7)!=0 |
|assertGreater(a,b)
| a>b |
|assertGreaterEqual(a,b)
| a>=b |
|assertLess(a,b)
| a<b |
|assertLessEqual(a,b)
| a<=b |
|assertRegex(s,r)
| r.search(s) |
|assertNotRegex(s,r)
| notr.search(s) |
|assertCountEqual(a,b)
| a and b have the same elements in the same number, regardless of their order. |
2.6 skip
当测试中出现某些原因我们不得不跳过一些测试用例的时候,需要用到skip()
的一些方法。
@unittest.skip(reason)
跳过被此装饰器装饰的测试。reason
为测试被跳过的原因。
@unittest.skipIf(condition,reason)
当condition
为真时,跳过被装饰的测试。
@unittest.skipUnless(condition,reason)
跳过被装饰的测试,除非condition
为真。
@unittest.expectedFailure
将测试标记为预期的失败或错误。如果测试失败或错误,它将被视为成功。如果测试通过,它将被视为失败。
exceptionunittest.SkipTest(reason)
引发此异常以跳过一个测试。
通常来说,你可以使用TestCase.skipTest()
或其中一个跳过测试的装饰器实现跳过测试的功能,而不是直接引发此异常。
被跳过的测试的**setUp()**
和**tearDown()**
不会被运行。被跳过的类的**setUpClass()**
和**tearDownClass()**
不会被运行。被跳过的模块的**setUpModule()**
和**tearDownModule()**
不会被运行。