Python单元测试unittest详解:从基础概念到Jenkins集成
本文深入解析Python标准库unittest的核心概念,包括TestCase、TestSuite及TestRunner的工作机制。详细演示如何编写测试用例、使用断言进行结果校验,并介绍通过HTMLTestRunner生成可视化报告。针对持续集成场景,进一步讲解如何利用xmlrunner模块生成Jenkins兼容的XML格式测试报告,实现自动化测试流程的完整闭环。
Python内置了名为unittest的单元测试框架,该模块封装了多种用于校验返回结果的方法以及用例执行前的初始化操作,是进行单元测试的常用工具。
作为Python的标准测试库,unittest是目前Python生态中使用最为广泛的测试框架,相较于其他第三方测试框架具有更高的普及率。
理解unittest需要掌握四个核心概念:test fixture(测试夹具)、test case(测试用例)、test suite(测试套件)以及test runner(测试执行器)。
在深入探讨unittest的具体用法之前,有必要先厘清上述几个关键概念的定义与作用。
TestCase即测试用例,是构成测试的基本单元,用于验证特定功能或逻辑的正确性。
TestSuite用于将多个独立的测试用例(TestCase)集合在一起,形成一个可执行的测试集合。
TestLoader负责将定义好的TestCase加载到TestSuite中,完成测试用例的组织工作。
TestRunner负责执行TestSuite中的测试用例,并将执行结果保存至TestResult实例中。TestResult记录了运行的测试数量、成功与失败的统计信息等关键数据。
通过执行dir(unittest)可以查看unittest模块包含的所有属性和方法,其内部类之间的层级与调用关系如图所示。

unittest主要类关系
标准的unittest调用流程如下:TestLoader自动将TestCase加载至TestSuite;随后TextTestRunner调用TestSuite的run方法,按顺序执行以test开头的方法并生成TestResult。在执行具体TestCase时,系统会先调用SetUp()进行环境准备,接着执行测试代码,最后调用tearDown()进行环境还原。
需要注意的是,TestLoader在加载TestCase时并不保证顺序。若单个TestCase中包含多个验证方法,其执行顺序将依据方法名中test后首字母的ASCII码值从小到大进行排序。
开发者可以手动调用TestSuite的addTest或addTests方法动态添加TestCase。这种方式不仅允许明确指定用例的执行顺序,还能避免强制要求验证方法必须以test开头。
以下是一个简单的单元测试用例示例,展示了基本结构。
import unittest
class MyTest(unittest.TestCase): # 继承unittest.TestCase
def tearDown(self):
# 每个测试用例执行之后做操作
print('111')
def setUp(self):
# 每个测试用例执行之前做操作
print('22222')
@classmethod
def tearDownClass(self):
# 必须使用 @ classmethod装饰器, 所有test运行完后运行一次
print('4444444')
@classmethod
def setUpClass(self):
# 必须使用@classmethod 装饰器,所有test运行前运行一次
print('33333')
def test_a_run(self):
self.assertEqual(1, 1) # 测试用例
def test_b_run(self):
self.assertEqual(2, 2) # 测试用例
if __name__ == '__main__':
unittest.main()#运行所有的测试用例
以下是常用的断言方法,用于校验测试执行后的结果是否符合预期。
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
若要生成可视化的测试报告,需引入第三方模块HTMLTestRunner。该模块需单独安装,执行测试用例后即可生成包含每个用例执行结果的HTML格式报告,具体代码实现如下。
import HTMLTestRunner
import unittest
class MyTest(unittest.TestCase):#继承unittest.TestCase
def tearDown(self):
#每个测试用例执行之后做操作
print('111')
def setUp(self):
#每个测试用例执行之前做操作
print(22222)
def test_run(self):
# self.assertEqual(1,1)
self.assertIs(1,1)
#测试用例
def test_run2(self):
# self.assertEqual(1,1)
self.assertIs(1,1)
#测试用例
def test_run3(self):
# self.assertEqual(1,1)
self.assertIs(1,1)
#测试用例
def test_run1(self):
# self.assertEqual(1,1)
self.assertIs(1,1)
#测试用例
if __name__ == '__main__':
test_suite = unittest.TestSuite()#创建一个测试集合
test_suite.addTest(MyTest('test_run1'))#测试套件中添加测试用例
#test_suite.addTest(unittest.makeSuite(MyTest))#使用makeSuite方法添加所有的测试方法
fp = open('res.html','wb')#打开一个保存结果的html文件
runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='api测试报告',description='测试情况')
#生成执行用例的对象
runner.run(test_suite)
#执行测试套件
当项目包含多个模块,且每个模块下存在大量Python文件及测试用例时,需要遍历目录下的所有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)
#运行测试
在持续集成(CI)场景中,通常使用Jenkins自动运行代码。由于Jenkins无法直接解析HTML格式的测试报告,因此需要生成Jenkins支持的XML格式报告。为此需安装xmlrunner模块(通过pip install xmlrunner),具体代码如下。
import unittest
import xmlrunner
#导入这个模块
class My(unittest.TestCase):
def test1(self,a,b,c):
self.assertEqual(a+b,c)
if __name__=='__main__':
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(My))
runner = xmlrunner.XMLTestRunner(output='report')#指定报告放的目录
runner.run(test_suite)
运行上述代码后,可在report目录下观察到生成的XML格式报告,且文件名已自动包含日期信息,便于版本追溯。

以上内容涵盖了Python unittest的核心用法及集成方案,希望对读者有所帮助,欢迎继续支持本站获取更多技术资源。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









