unittest

单元测试是对程序中最小的可测试模块——函数来进行测试。被测对象一定要有输出结果,哪怕是异常也需要有异常输出,只有这样单元测试才能够捕获返回值,并且与预期值进行比较,从而得出测试通过与否。

但是对于python自带的exception或者error输出,其实不显式指定是捕获不到的,那么应当如何处理这种情况呢?我个人的理解是这并不重要。比如因为传参类型报错,我们不可能对于各种情况都去进行unittest,并且都去在原函数中写exception,何况python自己就会报错告诉我们错在哪里。我们写unittest应该是我们所希望实现的函数功能是不是得到了正确实现,而不是报错。换言之,函数虽然可以运行但其实和我们预想的不一样这才是我们真正需要担心并unittest的地方!

unittest 框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cls
import unittest

class clsTestCase(unittest.TestCase):
def setUp(self):
self.cls = cls()
def teardown(self):
self.cls = None
def test_func1(self):
self.assertEqual(self.cls.func1,expect1)
def test_func2(self):
self.assertRaises(Exception,self.cls.func2,func2_params)

if __name__ '__main__':
unittest.main()

unittest代码基本是以上代码格式,需要注意的点:

  1. cls为需要测试的类。一般把unittest类名起为clsTestCase
  2. class需要继承unittest.TestCase
  3. 需要测试的函数必须都以test开头命名,不然测试不到。
  4. 如果是测试Exception,func的参数不能直接传进func里面,而应该写成 self.assertRaises(Exception,self.cls.func2,func2_params)
  5. 最好有def setUp 和 def teardown 两个函数,用于对class中每个test函数测试前的初始化和测试后的清空。

输出格式

如果希望对输出每个test func的测试情况,可以这样:

1
2
3
4
if __name__ == "__main__":
#unittest.main()
suite = unittest.TestLoader().loadTestsFromTestCase(clsTestCase)
unittest.TextTestRunner(verbosity=2).run(suite)

setUp&teardown

unittest module包含了编写运行unittest的功能,自定义的test class都要继承unitest.TestCase类,test method要以test开头,运行顺序根据test method的名字排序,特殊方法:

  1. setup():每个测试函数运行前运行
  2. teardown():每个测试函数运行完后执行
  3. setUpClass():必须使用@classmethod 装饰器,所有test运行前运行一次
  4. tearDownClass():必须使用@classmethod装饰器,所有test运行完后运行一次

unittest.skip

可以使用unitest.skip装饰器族跳过test method或者test class,这些装饰器包括:

  1. @unittest.skip(reason):无条件跳过测试,reason描述为什么跳过测试
  2. @unittest.skipif(conditition,reason):condititon为true时跳过测试
  3. @unittest.skipunless(condition,reason):condition不是true时跳过测试
1
2
3
4
5
#这是一个自定义的skip decorrator
def skipUnlessHasattr(obj, attr):
if hasattr(obj, attr):
return lambda func: func
return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

其他特殊方法

使用@unittest.expectedFailure装饰器,如果test失败了,这个test不计入失败的case数目

How to unit test complex methods

How to unit test complex methods

测试代码覆盖率

1
2
3
4
5
6
7
8
9
# 安装所需包
pip install coverage
# terminal运行unittest脚本
coverage run test_mymath.py
# 在终端打印出信息
coverage report -m
# 生成html文件夹
coverage html
# 用浏览器打开其中index.html

unittest报告

HTMLTestRunner_PY3 repo提供了报告生成脚本和使用范例。范例中也提供了测试用例集合的构造方法。

references

Python中unittest用法实例

如何测试代码覆盖率:coverage.py 简介

How to unit test complex methods

Python3 unittest单元测试

Python单元测试unittest