unittest框架
unittest是python自动测试框架,核心:test case, test suite, test runner, test fixture。
官方文档,python3版本:https://docs.python.org/zh-tw/3/library/unittest.html
1.Test Fixture
对于一个测试用例环境的搭建和销毁,是一个fixture。启用testfixture(测试执行前:需要准备测试环境,eg:连接数据库、打开浏览器等;测试执行后:还原数据库、关闭浏览器。)
- setUp():准备环境,执行每个测试用例的前置条件;
- tearDown():环境还原,执行每个测试用例的后置条件;
- setUpClass():必须使用哪@classmethod装饰器,所有case执行的前置条件,值运行一次;
- tearDownClass():必须使用@classmethod装饰器,所有case执行完成后只运行一次。
2.TestCase
一个class继承了unittest.TestCase,即是一个测试用例,测试方法以test开头;
测试环境准备setUp()|setUpClass()、执行代码run()、测试环境后还原tearDown()|tearDownClass()。
import unittest def add(a,b): return a+b def divide(a,b): return a/b class testfunc(unittest.TestCase): @classmethod def setUpClass(cls): print("开始") @classmethod def tearDownClass(cls): print("结束") def test_add(self): print("执行加法") self.assertEqual(3,add(1,2)) def test_divide(self): print("执行除法") if __name__ == '__main__': unittest.main()
前后各执行一次;如果用setUp()和tearDown(),会在每个test_func()前后各执行一次。
备注:unittest.main(verbosity=2),会输出详细的测试结果,verbosity默认值为1,若设置为0,则不输出用例的执行结果。
Console: test_add (__main__.testfunc) ... ok
test_divide (__main__.testfunc) ... ok
3.TestSuite
控制test测试用例的执行顺序,testsuit还可以包含testsuit。
if __name__ == '__main__': test = [testfunc("test_divide"), testfunc("test_add")] suite = unittest.TestSuite() suite.addTests(test) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
Console: test_divide (__main__.testfunc) ... ok
test_add (__main__.testfunc) ... ok
4.整体流程
- TestCase->TestLoader加载TestCase到TestSuite->TextTestRunner运行TestSuite,并将运行结果保存在TextTestResult中;
- 通过命令或者unittest.main()执行时,main会调用TextTestRunner中的run来运行;
- 或者可以通过TextTestRunner来执行用例;
- Runner执行时,默认将执行结果输出到控制台,可以使用HTMLTestRunner将结果输出到Html中。
5.Skip装饰器
skip装饰器主要有3种:
- unittest.skip(reason):无条件跳过执行,reason描述为什么跳过测试;
- unittest.skiplf(condition,reason):如果condition为True,跳过执行;
- unittest.skipUnless(condition,reason):如果condition不为True,跳过执行;
expected failure
:使用@unittest.expectedFailure
装饰器,如果test失败了,这个test不计入失败的case数目。
@unittest.skip("不想执行") def test_add(self): print("执行加法") self.assertEqual(3, add(1, 2))
console: test_add (__main__.testfunc) ... skipped '不想执行'
6.生成html格式的测试报告
unittest默认生成的测试报告是txt格式,使用的是TextTestRunner(),如果想要生成html报告,可以使用HtmlTestRunner代替TextTestRunner。
1.下载文件
- 下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html ,右键HTMLTestRunner.py文件另存为即可。
- 下载后放到python安装目录/Lib下,如我的路径为:C:UsersXXXAppDataLocalProgramsPythonPython36Lib。
2.修改文件
- 第94行,将import StringIO修改成import io
- 第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
- 第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
- 第766行,将uo = o.decode('latin-1')修改成uo = e
- 第772行,将ue = e.decode('latin-1')修改成ue = e
- 第631行,将print >> sys.stderr, ' Time Elapsed: %s' % (self.stopTime-self.startTime)修改成print(sys.stderr, ' Time Elapsed: %s' % (self.stopTime-self.startTime))
3.在工程目录中创建result.html
from HTMLTestRunner import HTMLTestRunner if __name__ == '__main__': f=open('./result.html','wb') runner = HTMLTestRunner(stream=f, title='MathFunc Test Report', description='用例执行情况',verbosity=2 ) runner.run(suite)
import unittest from HTMLTestRunner import HTMLTestRunner def add(a, b): return a + b def mix(a, b): return a * b def divide(a, b): return a / b class testfunc(unittest.TestCase): @classmethod def setUpClass(cls): print("开始") @classmethod def tearDownClass(cls): print("结束") @unittest.skipIf(3<1,"不想执行") def test_add(self): print("执行加法") self.assertEqual(3, add(1, 2)) def test_mix(self): print("执行乘法") self.assertEqual(3, mix(1, 2)) def test_divide(self): print("执行除法") self.assertEqual(3, divide(3, 1)) if __name__ == '__main__': test = [testfunc("test_divide"), testfunc("test_add")] suite = unittest.TestSuite() suite.addTests(test) f=open('./result.html','wb') runner = HTMLTestRunner(stream=f, title='MathFunc Test Report', description='用例执行情况',verbosity=2 ) runner.run(suite)