选择
语言选择
本次个人作业我选择的语言是Python,了解学习Python有一段时间了但是一直没有练习,所以这次玩蛇,使用的版本是Python3.6。
开发工具选择
我选择的IDE是Pycharm,个人认为Pycharm是一款不错的Py开发工具,用起来得心应手,unittset是py自带的包不需要安装直接引用即可,方便快捷。开发工具截图如下。
Python单元测试框架unittest
unittest简介
TestCase(测试用例)
一个testcase就是一个测试用例,包括测试前环境的搭建setUp,执行测试代码run,测试后环境的还原tearDown,是一个完整的测试单元。
TestSuite(测试套件)
多个testcase的集合
TestLoder
用来加载TestCase到TestSuite中
TextTestRunner
是来执行测试用例的
TextTestResult
保存测试结果的类
TestFixture
测试准备前和执行后要做到的工作
核心工作原理
unittest实例
准备待测方法
mathfunc.py
def add(a,b):return a+bdef minus(a,b):return a-bdef multi(a,b):return a*bdef divide(a,b):return a/b
编写测试方法
test_mathfunc.py
import unittest
from mathfunc import *class TestMathFunc(unittest.TestCase):#每个测试方法以test开头def test_add(self):self.assertEqual(3,add(1,2))self.assertNotEqual(3,add(2,2))def test_minus(self):self.assertEqual(1,minus(3,2))def test_multi(self):self.assertEqual(6,multi(2,3))def test_divide(self):self.assertEqual(2,divide(6,3))self.assertEqual(2.5,divide(5,2))if __name__ == '__main__':#verbosity 输出详细程度 0 1 2unittest.main(verbosity=2)
运行结果
测试通过
测试不通过
把除法/改为//(整除)报错如下图
TestSuite
上面的代码运行无序,如果我们写的用例有顺序的话,就需要用TestSuite,被添加到TestSuite中的case会被按照顺序执行。
编写test_suite.py代码如下
import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunnerif __name__ == '__main__':suite = unittest.TestSuite()tests = [TestMathFunc("test_add"), TestMathFunc("test_minus"), TestMathFunc("test_divide")]#addTests添加多个TestCase#addTest添加单个TestCase#suite.addTests(tests)suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))#suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc')]) 传入列表runner = unittest.TextTestRunner(verbosity=2)runner.run(suite)
addTests方法
传入一个TestCase对象的列表。
unittest.TestLoader().loadTestsFromName/Names
传入一个TestCase对象,这个对象里可以包含多个test_开头的方法,每个test_开头的方法处理的时候都可以理解为一个TestCase实例。
TestFixture
在实际测试中,我们可能会遇到这种情况,需要测试的方法中有的需要连接数据库,测试完毕需要还原数据,所以我们就需要一个准备环境的方法(setUp)还有清理环境的方法(TearDown),这就是TestFixture所包含的内容。
修改test_mathfunc.py如下
import unittest
from mathfunc import *class TestMathFunc(unittest.TestCase):#重写了TestCase的方法def setUp(self):print("开始测试之前的环境搭建")def tearDown(self):print("环境清理")def test_add(self):self.assertEqual(3,add(1,2))self.assertNotEqual(3,add(2,2))def test_minus(self):self.assertEqual(1,minus(3,2))def test_multi(self):self.assertEqual(6,multi(2,3))#skip装饰器@unittest.skip("我不想执行除法")#@unittest.skipIf(condition=,reason=) 当condition为true时跳过#@unittest.skipUnless(condition=,reason=) 为false时跳过def test_divide(self):self.assertEqual(2,divide(6,3))self.assertEqual(2.5,divide(5,2))if __name__ == '__main__':unittest.main(verbosity=2)
在实际测试中我们也可能会遇到这样的情况,开始测试前需要连接数据库,测试结束后关闭连接,不需要还原数据,只在开始和结束各自执行一次即可,setUpClass和tearDownClass的作用就是实现以上功能。
@classmethoddef setUpClass(cls):print("开始测试之前的环境搭建统一")@classmethoddef tearDownClass(cls):print("最后清理环境")
输出结果如下图
没有得到想要的结果,多次输出发现setUp和tearDown输出位置不定,猜想是因为不是单线程执行造成的,所以进行调试结果正确,暂存疑问。
跳过测试
有时候当某些条件的时候我们可能需要跳过测试,unittest也为我们提供了相应的方法
#@unittest.skipIf(condition=,reason=) 当condition为true时跳过#@unittest.skipUnless(condition=,reason=) 为false时跳过def test_divide(self):self.assertEqual(2,divide(6,3))self.assertEqual(2.5,divide(5,2))
执行结果如下
把结果保存到文件中
保存到文本文件中
with open('Unittest.txt','a') as f:runner = unittest.TextTestRunner(stream=f, verbosity=2)runner.run(suite)
会在项目目录下生成Unittext.txt文本文件,内容如下
test_add (test_mathfunc.TestMathFunc) ... ok
test_divide (test_mathfunc.TestMathFunc) ... ok
test_minus (test_mathfunc.TestMathFunc) ... ok
test_multi (test_mathfunc.TestMathFunc) ... ok----------------------------------------------------------------------
Ran 4 tests in 0.000sOK
生成HTML
需要HTMLTsetRunner文件
with open('HTMLReport.html', 'wb') as f:runner = HTMLTestRunner(stream=f, title="123", description="test", verbosity=2)runner.run(suite)
参考自