19.unittest原理

单元测试
单元测试(unit testing)是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,通常来讲,要根据实际状况去断定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中能够指一个窗口或一个菜单等。总的来讲,单元就是人为规定的最小的
被测功能模块。

html

unittest运行原理

 

 

TestCase:一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,经过运行这个测试单元,能够对某一个问题进行验证。python

TestSuite:而多个测试用例集合在一块儿,就是TestSuite,并且TestSuite也能够嵌套TestSuite。 TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,建立它们的实例,而后add到TestSuite中,再返回一个TestSuite实例。git

TextTestRunner:extTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。github

fixture:而对一个测试用例环境的搭建和销毁,是一个fixture。
一个class继承了unittest.TestCase,即是一个测试用例,但若是其中有多个以 test 开头的方法,那么每有一个这样的方法,在load的时候便会生成一个TestCase实例,如:一个class中有四个test_xxx方法,最后在load到suite中时也有四个测试用例。框架

在每个测试用例中能够重写 如下函数
setUp()该测试用例执行前的设置工做、
tearDown()该测试用例执行后的清理工做、
setUpClass()全部测试用例前的设置工做、
tearDownClass()全部测试用例执行后的清洗工做less

在每个测试用例中能够经过skip,skipIf,skipUnless装饰器跳过某个测试函数,或者用TestCase.skipTest方法跳过测试函数。ide

流程:写好TestCase,而后由TestLoader加载TestCase到TestSuite,而后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,咱们经过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者咱们能够直接经过TextTestRunner来执行用例。函数

注意说明:单元测试

一、TestLoader加载TestCase到TestSuite能够经过TestSuite实例对象的addTest()和addTests()方法向suite中添加case或suite测试

二、在Runner执行时,默认将执行结果输出到控制台,咱们能够设置其输出到文件,在文件中查看结果(你可能据说过HTMLTestRunner,是的,经过它能够将结果输出到HTML中,生成漂亮的报告,它跟TextTestRunner是同样的,从名字就能看出来,这个咱们后面再说)。

三、在进行测试时能够传递verbosity参数,用以控制执行结果的输出,0 是简单报告、1 是通常报告、2 是详细报告。

案例
业务函数

这里咱们随意写几个业务函数,表示咱们将要进行测试的功能函数。将功能函数文件存储成mathfunc.py

def add(a, b):
return a+b

def minus(a, b):
return a-b

def multi(a, b):
return a*b

def divide(a, b):
return a/b

TestCase测试用例
咱们经过测试用例用代码来实现每个测试的详细过程和针对测试目标要测试的内容。同目录下建立test_mathfunc.py

import unittest
from mathfunc import *

 

class TestMathFunc(unittest.TestCase):

# TestCase基类方法,全部case执行以前自动执行
@classmethod
def setUpClass(cls):
print("这里是全部测试用例前的准备工做")

# TestCase基类方法,全部case执行以后自动执行
@classmethod
def tearDownClass(cls):
print("这里是全部测试用例后的清理工做")

# TestCase基类方法,每次执行case前自动执行
def setUp(self):
print("这里是一个测试用例前的准备工做")

# TestCase基类方法,每次执行case后自动执行
def tearDown(self):
print("这里是一个测试用例后的清理工做")

@unittest.skip("我想临时跳过这个测试用例.")
def test_add(self):
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2)) # 测试业务方法add

def test_minus(self):
self.skipTest('跳过这个测试用例')
self.assertEqual(1, minus(3, 2)) # 测试业务方法minus

def test_multi(self):
self.assertEqual(6, multi(2, 3)) # 测试业务方法multi

def test_divide(self):
self.assertEqual(2, divide(6, 3)) # 测试业务方法divide
self.assertEqual(2.5, divide(5, 2))

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

注意:

skip装饰器一共有三个 unittest.skip(reason)、unittest.skipIf(condition,reason)、unittest.skipUnless(condition,reason),skip无条件跳过,skipIf当condition为True时跳过,skipUnless当condition为False时跳过。

每一个测试方法均以 test 开头,不然是不被unittest识别的。

其实每个test开头的方法都会加载为独立的测试用例。

在unittest.main()中加 verbosity 参数能够控制输出的错误报告的详细程度,默认是 1,若是设为 0,则不输出每一用例的执行结果。若是参数为2则表示输出详细结果。

TestSuite测试组
TestSuite用来控制多个测试用例和多个测试文件之间的测试顺序。(这里的示例中的几个测试方法并无必定关系,但以后你写的用例可能会有前后关系,须要先执行方法A,再执行方法B)

咱们添加到TestSuite中的case是会按照添加的顺序执行的。

下面咱们就来试下将测试用例加载到测试组中。进行测试并将测试结果输出。
下面的代码存储成

import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':
suite = unittest.TestSuite()

tests = [TestMathFunc("test_add"), TestMathFunc("test_minus"), TestMathFunc("test_divide")] # 添加测试用例列表
suite.addTests(tests) # 将测试用例列表添加到测试组中
suite.addTest(TestMathFunc("test_multi")) # 直接用addTest方法添加单个TestCase
# 用addTests + TestLoader。不过用TestLoader的方法是没法对case进行排序的
# loadTestsFromName(),传入'模块名.TestCase名'
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),相似,传入列表

# loadTestsFromTestCase(),传入TestCase
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))

# suite中也能够套suite

# 将测试结果输出到测试报告中
# with open('UnittestTextReport.txt', 'a') as f:
# runner = unittest.TextTestRunner(stream=f, verbosity=2)
# runner.run(suite)

# 将测试结果输出到测试报告html中
# with open('HTMLReport.html', 'w') as f:
# runner = HTMLTestRunner(stream=f,
# title='MathFunc Test Report',
# description='generated by HTMLTestRunner.',
# verbosity=2
# )
# runner.run(suite)

# 直接将结果输出到控制台
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

测试报告
上面咱们实现了将测试结果输出到功控制台、txt、html三种形式。其中html的输出须要加载HTMLTestRunner.py模块。下载地址:https://github.com/626626cdllp/Test/blob/master/python-unittest/HTMLTestRunner.py

三种输出结果只能选择一种,不能所有选择。

控制台输出:

 

 

txt输出:

 

 

html输出:


总结一下:unittest是Python自带的单元测试框架,咱们能够用其来做为咱们自动化测试框架的用例组织执行框架。unittest的流程:写好TestCase,而后由TestLoader加载TestCase到TestSuite,而后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,咱们经过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者咱们能够直接经过TextTestRunner来执行用例。一个class继承unittest.TestCase便是一个TestCase,其中以 test 开头的方法在load时被加载为一个真正的TestCase。verbosity参数能够控制执行结果的输出,0 是简单报告、1 是通常报告、2 是详细报告。能够经过addTest和addTests向suite中添加case或suite,能够用TestLoader的loadTestsFrom__()方法。用 setUp()、tearDown()、setUpClass()以及 tearDownClass()能够在用例执行前布置环境,以及在用例执行后清理环境咱们能够经过skip,skipIf,skipUnless装饰器跳过某个case,或者用TestCase.skipTest方法。参数中加stream,能够将报告输出到文件:能够用TextTestRunner输出txt报告,以及能够用HTMLTestRunner输出html报告。

相关文章
相关标签/搜索