一 、unittest是什么?
unittest是python内置的单元测试框架,具备编写用例、组织用例、执行用例、输出报告等自动化框架的条件。
使用unittest前需要了解该框架的五个概念:test case,test suite,testLoader,test runner,test fixture。
test case :一个完整的测试单元,执行该测试单元可以完成对某一个问题的验证。完整体现在:测试前环境准备(setUp),执行测试代码(run),以及测试后环境还原(tearDown);
test suite :多个测试用例的集合,测试套件或测试计划;
testLoader :加载TestCase到TestSuite中的,其中loadTestsFrom__()方法用于寻找TestCase,并创建它们的实例,然后添加到TestSuite中,返回TestSuite实例;
test runner :执行测试用例,并将测试结果保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息;
test fixture:一个测试用例的初始化准备及环境还原,主要是setUp() 和 setDown()方法;
二 、unittest的工作原理
通过unittest类调用分析,可将框架的工作流程概况如下:
编写TestCase,由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite, 最后将运行的结果保存在TextTestResult中。
三、unittest实战举例
了解了unittest框架的五大概念和工作流程后,接下来举例如何使用该框架对模块进行单元测试。
3.1 待测模块myfunc
myfunc包含两个函数:add(),divide(),代码如下:
def add(a,b):
return a+b
def divide(a,b):
return a/b
3.2 unittest编写测试用例
使用unittest对myfunc进行单元测试,首先需要导入unittest框架和待测模块myfunc,定义的测试用例方法类 需要继承 unittest.TestCase,且测试用例方法是以test_开头作为标识,用例的执行结果以assertxxx断言结果 决定,如果断言返回为false,将抛出assetError异常。测试用例代码如下:
import unittest
from MyFunc import add,divide
class TestMyFunc(unittest.TestCase): #定义测试方法类,需继承unittest.TestCase类
def setUp(self):
print('每个用例执行前会调用setUp方法准备环境')
def tearDown(self):
print('每个用例执行后会调用tearDown方法进行环境清理')
def test_divide(self): #测试用例以test_开头
print('divide')
self.assertEqual(2, divide(6, 3))
self.assertNotEqual(2, divide(5, 2))
def test_add(self): #用例默认按升序执行
print('add')
self.assertEqual(3,add(1,2))
self.assertNotEqual(3, add(2, 2))
if __name__ == '__main__':
unittest.main()
3.3 如何控制用例执行顺序
在unittest中,用例是以test开头的方法定义的,默认执行顺序是根据用例名称升序进行,如上面的用例,
实际执行顺序为:test_add–>test_divide–>test_is_prime,而不是用例定义的先后顺序。 在unittest中解决用例执行顺序的问题是使用TestSuite,代码如下:
import unittest
from MyFunc import add,divide
class TestMyFunc(unittest.TestCase): #定义测试方法类,需继承unittest.TestCase类
def setUp(self):
print('每个用例执行前会调用setUp方法准备环境')
def tearDown(self):
print('每个用例执行后会调用tearDown方法进行环境清理')
def test_divide(self): #测试用例以test_开头
print('divide')
self.assertEqual(2, divide(6, 3))
self.assertNotEqual(2, divide(5, 2))
def test_add(self): #用例默认按升序执行
print('add')
self.assertEqual(3,add(1,2))
self.assertNotEqual(3, add(2, 2))
if __name__ == '__main__':
tests=[TestMyFunc("test_divide"),TestMyFunc("test_add")]#使用TestSuite控制用例顺写,用例执行的顺序是由添加到TestSuite的顺序决定的
suite=unittest.TestSuite()
suite.addTests(tests) #将测试用例实例增加到测试套件中
runner=unittest.TextTestRunner()
runner.run(suite)
3.4 如何跳过用例
在自动化测试中,经常会遇到挑选用例的情况,实例代码如下:
import unittest
import sys
from MyFunc import add,divide
class TestMyFunc(unittest.TestCase): # 定义测试方法类,需继承unittest.TestCase类
def setUp(self):
print('每个用例执行前会调用setUp方法准备环境')
def tearDown(self):
print('每个用例执行后会调用tearDown方法进行环境清理')
def test_add(self):
print('add')
self.assertEqual(3,add(1,2))
self.assertNotEqual(3,add(2,2))
@unittest.skipUnless(sys.platform.startswith("mac"), "requires mac") # 跳过该用例
def test_divide(self):
print('divide')
self.assertEqual(2,divide(6,3))
self.assertNotEqual(2,divide(5,2))
if __name__ == '__main__':
unittest.main()
3.5 如何生成html格式的测试报告
Unittest中默认生成的报告格式为txt,如果想生成html格式的报告,可以使用HtmlTestRunner模块, 安装后导入该模块,使用HTMLTestRunner代替默认的TextTestRunner()执行测试用例即可。实例代码如下:
import unittest
from MyFunc import add,divide
from HtmlTestRunner import HTMLTestRunner
#https://pypi.org/project/html-testRunner/
#导入第三方htmltestrunner模块,执行结果生成html报告;pip install html-testRunner
class TestMyFunc(unittest.TestCase): #定义测试方法类,需继承unittest.TestCase类
def setUp(self):
print('每个用例执行前会调用setUp方法准备环境')
def tearDown(self):
print('每个用例执行后会调用tearDown方法进行环境清理')
def test_divide(self): #测试用例以test_开头
print('divide')
self.assertEqual(2, divide(6, 3))
self.assertNotEqual(2, divide(5, 2))
def test_add(self): #用例默认按升序执行
print('add')
self.assertEqual(3,add(1,2))
self.assertNotEqual(3, add(2, 2))
if __name__ == '__main__':
suite = unittest.TestSuite() suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMyFunc)) #使用TestLoader加载用例
runner = HTMLTestRunner(output='result')
runner.run(suite)