Reference:
廖雪峰-单元测试
单元测试主要用来对一个方法、一个类或者一个模块进行检查的。基于测试驱动开发(TDD)的思想,为了让编写的某个模块的代码能够通过提前写好的测试代码。
单元测试可考虑的级别https://www.zhihu.com/question/27313846/answer/120164282
我给自己的单元测试设置了5个级别:
- Level1:正常流程可用,即一个函数在输入正确的参数时,会有正确的输出
- Level2:异常流程可抛出逻辑异常,即输入参数有误时,不能抛出系统异常,而是用自己定义的逻辑异常通知上层调用代码其错误之处
- Level3:极端情况和边界数据可用,对输入参数的边界情况也要单独测试,确保输出是正确有效的
- Level4:所有分支、循环的逻辑走通,不能有任何流程是测试不到的
- Level5:输出数据的所有字段验证,对有复杂数据结构的输出,确保每个字段都是正确的
unittest
官方文档地址:https://docs.python.org/zh-cn/3/library/unittest.html#module-unittest
先来看一下unittest的工作原理:Python必会的单元测试框架 —— unittest
总结一下原理:
写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。这里加个说明,在Runner执行时,默认将执行结果输出到控制台,我们可以设置其输出到文件,在文件中查看结果
unittest使用步骤:
1.创建一个测试用例类继承unittest.TestCase类
2.测试方法名称以test开头,在测试方法内调用方法对预期输出和实际输出进行比较,方法包括不限于assertEqual(),assertTrue(),assertFalse(),assertRaises()。测试方法的执行顺序是按test后字母的顺序执行的。
3.使用unittest.main()来运行测试脚本,也可以通过在命令行使用python -m unittest 测试文件名.测试用例类名的方式进行调用,如下代码,我们使用python -m unittest -v testmodel.MyUnittest进行调用(其中-v可以直观的表现出每一个方法测试时的运行)
import unittest
class MyUnittest(unittest.TestCase):
def test_upper(self):
return self.assertEqual('foo'.upper(),'FOO')
if __name__ == '__main__':
unittest.main()
高阶:
- 如果需要每个用例开始或者结束之前都调用一次,用setUp()和tearDown()方法,这种用于的场景是:例如在UI自动化测试时,前置是需要打开浏览器,完成测试的操作后再把浏览器关闭?(实际上我觉得这种场景应该是用setUpClass...)
import unittest
class MyUnittest(unittest.TestCase):
def setUp(self):
print('preparing condition')
def tearDown(self):
print('test down')
def test_upper(self):
return self.assertEqual('foo'.upper(),'FOO')
def test_lower(self):
return self.assertEqual('FOO'.lower(),'foo')
if __name__ == '__main__':
unittest.main()
但是如果想要在整个测试类进行测试之前准备或释放环境资源,那么可以用@classmethod装饰器在setUpClass和tearDownClass前面。可以看这个博客的用法selenium中的setUp,tearDown与setUpClass,tearDownClass的区别及用例编写相关注意点 这个博客也提到了,在这种场景下,需要注意的是用例之间的耦合,不要让前一个用例的状态影响到了下一个用例。
- skip装饰器
包括三种,unittest.skip()、unittest.skipIf()、unittest.skipUnless(),下面是官方文档的一个例子:
class MyTestCase(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Tests that work for only a certain version of the library.
pass
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_windows_support(self):
# windows specific testing code
pass
def test_maybe_skipped(self):
if not external_resource_available():
self.skipTest("external resource not available")
# test code that depends on the external resource
pass
此外,也可以用expectedFailure()装饰器表明这个测试预计失败。
-
subTest()
Reference:单元测试框架之unittest上下文管理器subTest()
当在循环中判断时,如果判断结果不符合,我们的测试用例会直接停在当前fail的位置,使用subTest()可以让所有的输入都至少过一遍断言。 -
TestSuite指定测试方法的顺序
Python单元测试(一)--Unittest
网友评论