[关闭]
@hainingwyx 2018-12-07T13:26:25.000000Z 字数 2840 阅读 1112

单元测试之UnitTest

python 测试


单元测试,就是对一个模块,一个函数,或则是一个类进行正确性检测的一类测试工作。
单元测试不仅仅在测试的时候保障函数、模块或者类的功能符合我们的需求。同时,也有利于我们在未来修改类或者函数的时候,只需要再跑一遍单元测试就可以确保我们的修改对功能不会产生影响。

编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。

以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。

对每一类测试都需要编写一个test_xxx()方法。由于unittest.TestCase提供了很多内置的条件判断,我们只需要调用这些方法就可以断言输出是否是我们所期望的。最常用的断言就是assertEquals()

  1. self.assertEquals(abs(-1), 1) # 断言函数返回的结果与1相等

另一种重要的断言就是期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError

  1. with self.assertRaises(KeyError):
  2. value = d['empty']

运行单元测试

可以在测试程序中加入:

  1. if __name__ == '__main__':
  2. unittest.main()

这样可以把测试程序当正常脚本运行:

  1. $ python mydict_test.py

另一种更常见的方法是在命令行通过参数-m unittest直接运行单元测试:

  1. $ python -m unittest mydict_test

常用命令:

  1. $ python -m unittest -h

setUp与tearDown

可以在单元测试中编写两个特殊的setUp()tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。

setUp()tearDown()方法有什么用呢?设想你的测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库,这样,不必在每个测试方法中重复相同的代码:

  1. class TestDict(unittest.TestCase):
  2. def setUp(self):
  3. print 'setUp...'
  4. def tearDown(self):
  5. print 'tearDown...'

setUpClass 与 tearDownClass

setUpClass():一个类方法在单个类测试之前运行。setUpClass作为唯一的参数被调用时,必须使用classmethod作为装饰器。
tearDownClass():一个类方法在单个类测试之后运行。setUpClass作为唯一的参数被调用时,必须使用classmethod作为装饰器。

此外setUpModuletearDownModule不再详细介绍。

案例

业务函数, mathfunc.py

  1. def add(a, b):
  2. return a+b
  3. def minus(a, b):
  4. return a-b
  5. def multi(a, b):
  6. return a*b
  7. def divide(a, b):
  8. return a/b

测试用例, test_mathfunc.py

  1. import unittest
  2. from mathfunc import *
  3. class TestMathFunc(unittest.TestCase):
  4. # TestCase基类方法,所有case执行之前自动执行
  5. @classmethod
  6. def setUpClass(cls):
  7. print("这里是所有测试用例前的准备工作")
  8. # TestCase基类方法,所有case执行之后自动执行
  9. @classmethod
  10. def tearDownClass(cls):
  11. print("这里是所有测试用例后的清理工作")
  12. # TestCase基类方法,每次执行case前自动执行
  13. def setUp(self):
  14. print("这里是一个测试用例前的准备工作")
  15. # TestCase基类方法,每次执行case后自动执行
  16. def tearDown(self):
  17. print("这里是一个测试用例后的清理工作")
  18. @unittest.skip("我想临时跳过这个测试用例.")
  19. def test_add(self):
  20. self.assertEqual(3, add(1, 2))
  21. self.assertNotEqual(3, add(2, 2)) # 测试业务方法add
  22. def test_minus(self):
  23. self.skipTest('跳过这个测试用例')
  24. self.assertEqual(1, minus(3, 2)) # 测试业务方法minus
  25. def test_multi(self):
  26. self.assertEqual(6, multi(2, 3)) # 测试业务方法multi
  27. def test_divide(self):
  28. self.assertEqual(2, divide(6, 3)) # 测试业务方法divide
  29. self.assertEqual(2.5, divide(5, 2))
  30. if __name__ == '__main__':
  31. unittest.main(verbosity=2)

注意:

小结

单元测试可以有效地测试某个程序模块的行为,是未来重构代码的信心保证。
单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。
单元测试代码要非常简单,如果测试代码太复杂,那么测试代码本身就可能有bug。
单元测试通过了并不意味着程序就没有bug了,但是不通过程序肯定有bug。

参考文献

https://segmentfault.com/a/1190000008048642
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00140137128705556022982cfd844b38d050add8565dcb9000
https://juejin.im/entry/576026f85bbb500063d67880
https://blog.csdn.net/luanpeng825485697/article/details/79459771

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注