2. unittest 使用¶
Note
unittest 是python 最常用的单元测试框架.支持自动化测试,测试代码共享启动和关闭代码,集合测试以等。有几个概念:
- test fixture: 开始测试前所作的工作,一般使用setUp()和tearDown()函数完成。
- test case: 测试案例,最小的测试单元
- test suite: 测试套件,测试案例的集合
- test runner: 运行测试
命名方法:
- 测试类 以
Test开头 - 测试方法 以
test开头
测试要用到 assert 断言语法
python assert 断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
2.1. test fixture¶
测试开始和结束的准备工作,一般用于创建和关闭数据库连接,开始或停止一个进程等, 如果是一系列测试需要相同的准备和结束工作,那建议写一个基类定义它们,具体测试在继承它
只需要定义下面两个函数:
setUp开始前的准备和tearDown结束后的操作
例:
base_case.py
base_case.py¶
1 2 3 4 5 6 | class BaseTestCase(unittest.TestCase):
def setUp(self):
self.redis = redis.StrictRedis(host='192.168.137.3', db=6)
def tearDown(self):
self.redis.flushdb() # 清空
|
2.2. test case¶
通过继承 unittest.TestCase 或是自己的 unittest.TestCase 基类,就可以创建测试单元,测试方法 都是以 ``test``开头。
如:
test_case.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # coding:utf-8
from __future__ import absolute_import, unicode_literals
import unittest
from .base_case import BaseTestCase
__author__ = "golden"
__date__ = '2017/8/11'
class TestString(BaseTestCase):
def setUp(self):
super(TestString, self).setUp()
self.redis.set('test_string', 'python')
def test_get_string_is_str(self):
assert not isinstance(self.redis.get('test_string'), str)
def test_get_string_is_bytes(self):
assert isinstance(self.redis.get('test_string'), bytes)
def test_get_string_value(self):
assert self.redis.get('test_string') == 'python'
class TestHash(BaseTestCase):
def setUp(self):
super(TestHash, self).setUp()
self.redis.hset('test_hash', 'key1', 'value1')
self.redis.hset('test_hash', 'key2', 'value2')
def test_get_all(self):
res = self.redis.hgetall('test_hash')
print(res)
assert isinstance(res, dict)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestString)
unittest.main(defaultTest=suite)
|
最后目录结构为:
- unit_test :
__init__.pybase_case.pytest_case.pytest_suite.py
要执行测试,可以在命令行执行命令: python -m unittest unit_test.case 得到下面结果:
> python -m unittest unit_test.test
{b'key1': b'value1', b'key2': b'value2'}
...F # 成功三个,失败一个
======================================================================
FAIL: test_get_string_value (unit_test.test.TestString)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\operation-platform\source\_static\unit_test\test.py", line 22, in test_get_string_value
assert self.redis.get('test_string') == 'python'
AssertionError
----------------------------------------------------------------------
Ran 4 tests in 0.016s
FAILED (failures=1) # 失败一个
2.3. test suite¶
测试套件是测试单元的集合,构建测试套件需要用到 unittest.TestSuite() 类,我们一般写成一个方法,如:
test_suite.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # coding:utf-8
from __future__ import absolute_import, unicode_literals
import unittest
__author__ = "golden"
__date__ = '2017/8/11'
from .test_case import *
def suite1():
test_suite = unittest.TestSuite()
test_suite.addTest(TestHash('test_get_all'))
test_suite.addTest(TestString('test_get_string_is_str'))
return test_suite
def suite2():
tests = ['test_get_string_value', 'test_get_string_is_str']
return unittest.TestSuite(map(TestString, tests))
def all(): # 多个套件还可以构成更大的套件
_suite1 = suite1()
_suite2 = suite2()
return unittest.TestSuite([_suite1, _suite2])
|
运行命令 python -m unittest unit_test.test_suite.suite1 结果如下:
> python -m unittest unit_test.test_suite.suite1
{b'key2': b'value2', b'key1': b'value1'}
..
----------------------------------------------------------------------
Ran 2 tests in 0.009s # 只运行了两个测试
OK
2.4. 跳过测试和预期的失败¶
由几个装饰器来控制:
@unittest.skip(reason)由什么原因跳过测试@unittest.skipIf(condition, reason)满足 condition 条件时跳过@unittest.skipUnless(condition, reason)不满足 条件时跳过@unittest.expectedFailure如果失败 ,不包含在失败结果中exception unittest.SkipTest(reason)报错错误- 装饰器都可以用于方法或类
2.5. 提供的其他测试方法¶
还有一些其他的测试方法,如:
- assertEqual(a, b) a == b
- assertNotEqual(a, b) a != b
- assertTrue(x) bool(x) is True
- assertFalse(x) bool(x) is False
- assertIs(a, b) a is b 3.1
- assertIsNot(a, b) a is not b 3.1
- assertIsNone(x) x is None 3.1
- assertIsNotNone(x) x is not None 3.1
- assertIn(a, b) a in b 3.1
- assertNotIn(a, b) a not in b 3.1
- assertIsInstance(a, b) isinstance(a, b) 3.2
- assertNotIsInstance(a, b) not isinstance(a, b) 3.2
详见 其他