python单元测试之模块TestCase
初步认识
TestCase是单元测试中最常用的类,例如,接下来测试下面这个小函数
add = lambda a,b : a+b
div = lambda a,b : a/b
其测试方法为
import unittest
class TestTest(unittest.TestCase):
def test_div(self):
self.assertEqual(0,div(1,5))
def test_add(self):
self.assertEqual(3,add(1,2))
unittest.main()
在执行上述语句之后,返回如下信息,然后退出了python。
>>> unittest.main()
.F
======================================================================
FAIL: test_div (__main__.TestTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 3, in test_div
AssertionError: 0 != 0.2
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=1)
需要注意的是,在调用测试类的时候,可以直接实用unittest.main函数。其中assertEqual是TestCase中封装的一个断言函数,当输入变量不相等时会报出断言错误。
断言函数
其实掌握了assertEqual,就可以满足很多的测试需求了,而TestCase中提供了很多断言方法,有些可成对出现,下表中称之为逆断言,若断言为assertXXX,则其逆断言写为assertNotXXX,参数相同。如果断言为真,则逆断言为假。
| 用于判断相等 | 真值情况 | 逆断言 |
|---|---|---|
assertEqual(a, b) | a == b | assertNotEqual |
assertTrue(x) | x | |
assertFalse(x) | !x | |
assertIs(a, b) | a is b | assertIsNot |
assertIsNone(x) | x is None | assertIsNotNone |
assertIn(a, b) | a in b | assertNotIn |
assertIsInstance(a, b) | isinstance | assertNotIsInstance |
其中,assertEqual可以自动选用不同类型的比较方法,这些方法为
| Method | 用作比较 | Method | 用作比较 |
|---|---|---|---|
assertMultiLineEqual | 字符串 | assertSequenceEqual | 序列 |
assertListEqual | 列表 | assertTupleEqual | 元组 |
assertSetEqual | 集合 | assertDictEqual | 字典 |
此外,还可以通过addTypeEqualityFunc来注册新的比较函数,从而可以让assertEqual对任何对象以任意的规则进行比较。
下面是用于比较大小的断言函数
| 用于比较 | 真值情况 | 逆断言 |
|---|---|---|
assertAlmostEqual(a, b) | round(a-b, 7) == 0 | assertNotAlmostEqual |
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) |
assertCountEqual(a, b) | a和b中的相同元素个数相同 |
其中assertAlmostEqual和assertNotAlmostEqual中,调节二者相似程度的参数为places,默认为7。
下面的这些断言用于测试函数,其中,exc和warn表示当函数测试失败时弹出的报错和警告信息。
| 测试内容 | |
|---|---|
assertRaises(exc, fun, *args, **kwds) | fun(*args, **kwds) 报错 |
assertRaisesRegex(exc, r, fun, *args, **kwds) | fun(*args, **kwds) 报错且报错信息匹配r |
assertWarns(warn, fun, *args, **kwds) | fun(*args, **kwds) 警告 |
assertWarnsRegex(warn, r, fun, *args, **kwds) | fun(*args, **kwds) 警告且报错信息匹配r |
assertLogs(logger, level) | with block中记录最低级别日志 |
assertNoLogs(logger, level) |
通过dir查看,除了一些已经弃用的断言函数之外,还有一个assertDictContainsSubset,并没有在官方文档上找到是干嘛的。
所有这些断言函数都有参数msg,用以输出报错信息。在TestCase类中有一个成员变量longMessage,若longMessage为False,则在遇到标准错误时将会输出自定义报错信息;否则的话自定义信息将会追加在标准错误信息的末尾。
maxDiff变量则会调整输出信息的尺寸,默认为80*8个字符。
run过程
可以认为TestCase中的run函数是主要执行测试的函数。
查看run函数的源码,发现这个函数还有一个输入参数为result,若未定义,则会通过调用defaultTestResult()新建一个临时对象,来启动测试程序。
在run的执行过程中,会优先考虑当前测试是否启用了skip,若__unittest_skip__为True,则会return。
如果未被忽略,则会进行测试,而在测试前后,会分别调用setUp以及tearDown,重载这两个函数可以直观地理解二者的作用时机
在编写自己的测试类的时候,需要继承TestCase,如果想在每次测试前后对测试环境进行初始化和恢复,则需要重载setUp以及tearDown。
import unittest
class TestTest(unittest.TestCase):
def test_div(self):
print("test div")
self.assertEqual(0.2,div(1,5))
def test_add(self):
print("test add")
self.assertEqual(3,add(1,2))
def setUp(self):
print("test start")
def tearDown(self):
print("test end")
这时再进行测试,则会得到
>>> unittest.main()
test start
test add
test end
.test start
test div
test end
.
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
可见,每个测试函数在执行之前,都会调用一次setUp,而测试函数结束时则会调用tearDown。如果想只调用一次,则需重载setUpClass以及tearDownClass。
在tearDown之后,会执行doCleanups,这个函数是更加强大的清除工具,无论测试是否成功,均会执行。其执行的功能,则通过addCleanup来添加。这两个方法同样有类的形式:doClassCleanups和addClassCleanup。
##其他方法和变量
countTestCases():返回当前对象的测试个数id():返回当前测试case的字符串标识shortDescription():返回当前测试的一个描述
更多推荐
所有评论(0)