unittest中最核心的四个概念是:test case, test suite, test runner, test fixture
- 一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
- 而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。
- TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。
- TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。 - 而对一个测试用例环境的搭建和销毁,是一个fixture。
一个class继承了unittest.TestCase,便是一个测试用例,但如果其中有多个以 test
开头的方法,那么每有一个这样的方法,在load的时候便会生成一个TestCase实例,如:一个class中有四个test_xxx方法,最后在load到suite中时也有四个测试用例。
写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。这里加个说明,在Runner执行时,默认将执行结果输出到控制台,我们可以设置其输出到文件,在文件中查看结果(你可能听说过HTMLTestRunner,是的,通过它可以将结果输出到HTML中,生成漂亮的报告,它跟TextTestRunner是一样的,从名字就能看出来,这个我们后面再说)
用到TestSuite原因:1添加到TestSuite中的case是会按照添加的顺序执行的。2但如果有多个测试文件,怎么进行组织,总不能一个个文件执行吧,答案也在TestSuite中。TestSuite 相当于一个容器,用来装testcase
一:编写测试用例
编写自己的测试用例必须继承TestCase类:class xx(unittest.TestCase):
初始化测试环境:
setUp和tearDown在每次执行case前后都执行了一次。
如果想要在所有case执行之前准备一次环境,并在所有case执行结束之后再清理环境,我们可以用 setUpClass() 与 tearDownClass():
class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py"""
@classmethod
def setUpClass(cls):
print
"This setUpClass() method only called once."
@classmethod
def tearDownClass(cls):
print
"This tearDownClass() method only called once too."
二:执行测试用例,
执行测试用例有两种方法:
- 若是在测试用例所在的文件内执行用例,直接用 Unittest.main() 方法执行,main()方法会自动执行本文件中所有以test* 命名的函数,
- 如果想将测试用例的文件和执行测试用例的文件分开来执行,需要以下顺序来写执行用例的代码:
A)导入模块:unittest,HTMLTestRunner(或TextTestRunner),测试用例模块
B):suite = unittest.TestSuite() 创建一个名字为suite 的容器,用来装testcase
C):suite.addTest(TestMathFunc(
"test_multi")) 用addTest()方法将case添加容器中 添加的是某一个测试用例
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) 通过
loadTestsFromTestCase()将case传入TestCase中,添加的是测试类中的所有用例,loadTestsFromModule(module):返回一个给定的模块中所有测试用例,
打包成一个套件返回。该类创建一个testsuites然后加载一个module并执行其中所有的测试用例,,执行的顺序是根据测试用例的名称来的: suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)
D):1) with open(
'UnittestTextReport.txt',
'a')
as f:
runner = unittest.TextTestRunner(stream=f, verbosity=
2)
通过TextTestRunner()方法来规定执行的测试用例结果输出到unittestTextReport.txt 文件中
2)
with open(
'HTMLReport.html',
'w')
as f:
runner = HTMLTestRunner(stream=f,
title=
'MathFunc Test Report',
description=
'generated by HTMLTestRunner.',
verbosity=
2
)
TextTestRunner()方法放到指定的txt文件中,或者通过
测试用例执行后的输出结果可以通过HTMLTestRunner()方法放到指定的html文件中,以网页形式展现,
E):runner.run(suite) 执行用例
3)若在某个目录下写了很多Python文件,每个文件中都有测试测试用例,现在想让这个文件中的所以测试用例都自动执行,需要以下方法:
import unittest,HTMLTestRunner
suite = unittest.TestSuite()#创建测试套件
all_cases = unittest.defaultTestLoader.discover('.','test_*.py')
#找到某个目录下所有的以test开头的Python文件,
for case in all_cases:
suite.addTests(case)#把所有的测试用例添加进来
fp = open('res.html','wb')
runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='all_tests',description='所有测试情况')
runner.run(suite)
#运行测试
discover(start_dir, pattern='test*.py',top_level_dir=None)
递归查找指定目录(start_dir)及其子目录下的全部测试模块,将这些测试模块放入一个TestSuite 对象并返回。只有匹配pattern的测试文件才会被加载到TestSuite中。
如果一个测试文件的名称符合pattern,将检查该文件是否包含 load_tests() 函数,如果 load_tests() 函数存在,则由该函数负责加载本文件中的测试用例。如果不存在,就会执行loadTestsFromModule(),查找该文件中派生自TestCase 的类包含的 test 开头的方法。
@unittest.skip("I don't want to run this case.")
def test_divide(self):
"""Test method divide(a, b)"""
print
"divide"
self.assertEqual(
2, divide(
6,
3))
self.assertEqual(
2.5, divide(
5,
2))
@unittest.skip:此方法用来跳过某个testcase不去执行
Unittest 中的方法:1.检测元素是否相等:assertEqual(a,b [,msg]):检测a==b,这个方法检查a是否等于b,常用语检测元素属性等。assertNotEqual(a,b [,smg]):检测a!==b.
2. 检测表达式是否为Ture,或者 False: assertTrue(x [,msg]) assertFalse(x [,msg])
3. 逻辑运算
assertGreater(a, b) # 检测a > b.
assertGreaterEqual(a ,b) # 检测a >= b.
assertLess(a, b) #检测a < b.
assertLessEqual(a, b) #检测a <= b.="" <="" code=""></=>