目录
unittest的简单概述:
Python中有一个自带的单元测试框架是unittest模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作
在说unittest之前,先说几个概念:
unittest中的几大核心部分:test fixture test case test suite test runner
- TestCase 也就是测试用例,是测试的最小单位,一般检查一组输入的响应和输出是否符合预期,unittest模块提供了TestCase类来帮助我们创建测试用例
- TestSuite 多个测试用例集合在一起,就是TestSuite(测试套件),例如:我们有50个测试用例,但是本次需要使用20个测试用例,可以将这20个组成一个测试套件。
- TestFixture是代表了用力执行前的准备工作和用例执行后的清理工作
- TestRunner是来执行测试用例并输出测试结果的组件,测试的结果会保存到TestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息,可以图形界面或者命令行界面。
各种demo
demo1(入门款demo)
import unittest
class Mytest(unittest.TestCase):
def test_01(self):
print('test01')
def est_02(self):
print('test02')
if __name__ == '__main__':
unittest.main()
执行后的结果为:
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
..
----------------------------------------------------------------------
Ran 1 tests in 0.000s
OK
test01
Process finished with exit code 0
由此可的:1、测试用例必须继承自unittest.TestCase
2、case均以test开头
demo2(增加setup和teardown)
import unittest
class Mytest(unittest.TestCase):
#test fixture
def setUp(self):
#用例执行前的准备
print('start....')
#test case
def test_01(self):
print('test01')
#test case
def test_02(self):
print('test02')
#test fixture
def tearDown(self):
#用例执行后的清理工作
print('end....')
if __name__ == '__main__':
unittest.main()
执行后的结果为:
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
start....
test01
end....
start....
test02
end....
Process finished with exit code 0
由此可得:测试用例的执行顺序是setUp--test01--tearDown--setUp--test02--tearDown
demo2(增加test suite)
import unittest
class Mytest(unittest.TestCase):
def setUp(self):
#用例执行前的准备
print('start....')
def test_01(self):
print('test01')
def test_02(self):
print('test02')
def tearDown(self):
#用例执行后的清理工作
print('end....')
class Mytest2(unittest.TestCase):
def setUp(self):
#用例执行前的准备
print('start2....')
def test_03(self):
print('test03')
def test_04(self):
print('test04')
def tearDown(self):
#用例执行后的清理工作
print('end2....')
if __name__ == '__main__':
mysuite = unittest.TestSuite()
mysuite.addTest(Mytest2('test_03'))
mysuite.addTest(Mytest('test_01'))
unittest.TextTestRunner(verbosity=2).run(mysuite)
执行后的结果为:
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
start2....
test_03 (__main__.Mytest2) ... ok
test03
end2....
test_01 (__main__.Mytest) ... ok
start....
test01
end....
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Process finished with exit code 0
由此可得:将测试套件实例化---将本次要执行的测试用例放到测试套件中---执行该套件
可但是但可是,unittest.TextTestRunner(verbosity=2).run(mysuite)中的参数又都是什么呢?
- verbosity 分别三个级别: 0 1 2 它们输出的测试报告详细程度不同,2 最详细
- stream 关系着测试报告的位置,如果默认为None的话,测试报告会输出到控制台,如果需要保存到某个文件,可以搞一个文件对象,然后将最终打印的日志保存到该文件中,就是修改该对象。
- descriptions 测试报告的描述
当verbosity=0时:执行上面的代码
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
start2....
----------------------------------------------------------------------
test03
Ran 2 tests in 0.000s
end2....
start....
OK
test01
end....
Process finished with exit code 0
当verbosity=1时:执行上面的代码
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
..
start2....
----------------------------------------------------------------------
test03
Ran 2 tests in 0.000s
end2....
start....
test01
end....
OK
Process finished with exit code 0
当verbosity=2时:执行上面的代码
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
start2....
test03
end2....
start....
test01
end....
test_03 (__main__.Mytest2) ... ok
test_01 (__main__.Mytest) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Process finished with exit code 0
不同的verbosity显示详细程度不同,0的时候只显示代码中需要print的,1的时候会显示..,2的时候显示具体的case成功的日志。
demo3(将结果搞到文件中)
if __name__ == '__main__':
mysuite = unittest.TestSuite()
mysuite.addTest(Mytest2('test_03'))
mysuite.addTest(Mytest('test_01'))
with open('./log.log','w+') as f:
unittest.TextTestRunner(verbosity=2,stream = f).run(mysuite)
将上面的代码进行更改后,就会将文件保存到log.log中,此时控制台显示:
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
test03
test01
Process finished with exit code 0
其中详细的内容显示在了log.log中:
unittest的断言
断言是测试用例的核心,我们使用assertEqual()来判断预期结果,使用assertTrue(),assertFalse()来做是非判断。
可以参考该文章:https://www.cnblogs.com/cindy-cindy/p/8243785.html
demo:将上面的代码稍微改动下
import unittest
class Mytest(unittest.TestCase):
def setUp(self):
#用例执行前的准备
pass
# print('start....')
def test_01(self):
print('test01')
def test_02(self):
print('test02')
def tearDown(self):
#用例执行后的清理工作
pass
# print('end....')
class Mytest2(unittest.TestCase):
def setUp(self):
#用例执行前的准备
pass
# print('start2....')
def test_03(self):
print('test03')
self.assertEqual('1','2')
def test_04(self):
print('test04')
def tearDown(self):
#用例执行后的清理工作
pass
# print('end2....')
if __name__ == '__main__':
mysuite = unittest.TestSuite()
mysuite.addTest(Mytest2('test_03'))
mysuite.addTest(Mytest('test_01'))
unittest.TextTestRunner(verbosity=2).run(mysuite)
执行后的结果:会显示具体哪个case错误了
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
test03
test_03 (__main__.Mytest2) ... FAIL
test01
test_01 (__main__.Mytest) ... ok
======================================================================
FAIL: test_03 (__main__.Mytest2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/dongyue/Desktop/code/learn/测试demo.py", line 32, in test_03
self.assertEqual('1','2')
AssertionError: '1' != '2'
- 1
+ 2
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
Process finished with exit code 0
当为verbosity = 1的时候:就只显示F.
/Users/dongyue/Desktop/code/venv/bin/python /Users/dongyue/Desktop/code/learn/测试demo.py
F.
test03
======================================================================
test01
FAIL: test_03 (__main__.Mytest2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/dongyue/Desktop/code/learn/测试demo.py", line 32, in test_03
self.assertEqual('1','2')
AssertionError: '1' != '2'
- 1
+ 2
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
Process finished with exit code 0
unittest的命令行
unittest支持命令行接口,我们可以在命令行里指定运行具体的测试用例
- 运行测试模块:python -m unittest 测试demo.py 测试demo2.py
- 运行测试类:python -m unittest 测试demo.Mytest
- 运行测试方法:python -m unittest 测试demo.Mytest.test_01
- 可以通过使用-v参数获取更详细的测试信息:python -m unittest -v 测试demo.py
- 可以通过-h参数查看命令行所有参数:python -m unittest -h
代码为:
import unittest
class Mytest(unittest.TestCase):
def setUp(self):
#用例执行前的准备
pass
# print('start....')
def test_01(self):
print('test01')
def test_02(self):
print('test02')
def tearDown(self):
#用例执行后的清理工作
pass
# print('end....')
class Mytest2(unittest.TestCase):
def setUp(self):
#用例执行前的准备
pass
# print('start2....')
def test_03(self):
print('test03')
self.assertEqual('1','2')
def test_04(self):
print('test04')
def tearDown(self):
#用例执行后的清理工作
pass
# print('end2....')
if __name__ == '__main__':
mysuite = unittest.TestSuite()
mysuite.addTest(Mytest2('test_03'))
mysuite.addTest(Mytest('test_01'))
with open('./log.log','w+') as f:
unittest.TextTestRunner(verbosity=2,stream = f).run(mysuite)
命令行命令为: python -m unittest -v 测试demo.py
终端执行结果显示为:
(venv) dongyuedeMacBook-Pro:learn dongyue$ python -m unittest -v 测试demo.py
test_01 (测试demo.Mytest) ... test01
ok
test_02 (测试demo.Mytest) ... test02
ok
test_03 (测试demo.Mytest2) ... test03
FAIL
test_04 (测试demo.Mytest2) ... test04
ok
======================================================================
FAIL: test_03 (测试demo.Mytest2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/dongyue/Desktop/code/learn/测试demo.py", line 32, in test_03
self.assertEqual('1','2')
AssertionError: '1' != '2'
- 1
+ 2
----------------------------------------------------------------------
Ran 4 tests in 0.001s
FAILED (failures=1)
(venv) dongyuedeMacBook-Pro:learn dongyue$