目录
示例2:setUpClass()和tearDownClass()
示例3:通过在测试用例方法名中添加数字test_N指定执行顺序
unittest核心工作原理
转载于文章Python必会的单元测试框架 —— unittest
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是一样的,从名字就能看出来)。
unittest示例
示例1:简单示例
#encoding=utf-8
import unittest
import random
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
# 初始化一个递增序列
self.seq = list(range(10))
print ("setup completed!")
def test_run(self):
# 从序列seq中随机选取一个元素
element = random.choice(self.seq)
# 验证随机元素确实属于列表中
self.assertTrue(element in self.seq)
def test_sth(self):
assert 1==2
def tearDown(self):
print ("tearDown completed")
class TestDictValueFormatFunctions(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
print("setup is ready!")
def test_shuffle(self):
# 随机打乱原seq的顺序
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))
# 验证执行函数时抛出了TypeError异常
self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
def tearDown(self):
print ("tearDown is Done!")
if __name__ == '__main__':
unittest.main()
执行结果:
setup is ready!
tearDown is Done!
.setup completed!
tearDown completed
.setup completed!
tearDown completed
F
======================================================================
FAIL: test_sth (__main__.TestSequenceFunctions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "F:\unittest\e1_unittest_demo.py", line 17, in test_sth
assert 1==2
AssertionError
----------------------------------------------------------------------
Ran 3 tests in 0.027s
FAILED (failures=1)
说明:
- 可以看到一共运行了3个测试用例,2个成功,1个失败,并给出失败原因:1==2
- 每一个用例执行的结果的标识,成功是
.
,失败是F
,出错是E
,跳过是S
- setUp()和tearDown()分别执行了3次,在每个测试用例执行前后分别执行了setUp和tearDown方法
- 每个测试方法均以
test
开头,否则是不被unittest识别的- 可以看到测试的执行跟方法写的位置顺序没有关系,测试用例的默认执行顺序是根据用例名的字母顺序来的,先执行了TestDictValueFormatFunctions类中的test_shuffle,然后执行了TestSequenceFunctions类中的test_run,最后执行了TestSequenceFunctions中类的test_sth
示例2:setUpClass()和tearDownClass()
#encoding=utf-8
import unittest
# 被测试类
class myclass(object):
@classmethod
def sum(self, a, b):
return a + b #将两个传入参数进行相加操作
@classmethod
def sub(self, a, b):
return a - b #将两个传入参数进行相减操作
class mytest(unittest.TestCase):
@classmethod
def setUpClass(cls):#每个测试类的setUpClass方法,只会执行一次
"初始化类固件"
print ( "----setUpClass")
@classmethod
def tearDownClass(cls):#每个测试类的tearDownClass方法,只会执行一次
"重构类固件"
print ( "----tearDownClass")
# 初始化工作
def setUp(self):#每个测试方法均会执行一次
self.a = 3
self.b = 1
print ( "--setUp")
# 退出清理工作
def tearDown(self):#每个测试方法均会执行一次
print ( "--tearDown")
# 具体的测试用例,一定要以test开头
def testsum(self):
# 断言两数之和的结果是否是4
self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail')
def testsub(self):
# 断言两数之差的结果是否是2
self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail')
if __name__ == '__main__':
unittest.main() # 启动单元测试
执行结果:
----setUpClass
--setUp
--tearDown
.--setUp
--tearDown
.----tearDownClass
----------------------------------------------------------------------
Ran 2 tests in 0.011s
OK
说明:
setUpClass()和tearDownClass()分别在每个测试类执行前后各执行一次(不管这个测试类中有多少个测试方法,它们都仅执行一次);而setUp()和tearDown()分别在每个测试方法执行前后各执行一次。