Python Unittest单元测试框架原理与实战指南

纸上星河
纸上星河
发布时间:2026-10-14| 3人浏览过
原创

本文详细介绍Python标准库unittest的核心原理与使用方法。内容涵盖测试类的继承、Setup/TearDown生命周期管理、TestSuite测试集构建、多种断言方式及错误处理机制,以及如何生成TXT和HTML格式的测试报告。通过具体代码示例,帮助开发者掌握自动化测试的最佳实践。

Unittest基本使用步骤

使用Python标准库unittest进行单元测试,主要遵循以下基本步骤:

首先,需要导入unittest模块。

其次,创建一个新的类,并使其继承自unittest.TestCase基类。

接着,在该类中定义以test为前缀的函数,这些函数将作为具体的测试用例。注意,函数名必须以test开头,这是框架识别测试用例的关键规则。

在执行具体的测试用例之前,框架会自动调用setUp函数(针对每个测试用例执行一次)或者setUpClass函数(针对所有测试用例仅执行一次),用于初始化测试环境。

测试用例执行完毕后,框架会调用tearDown函数(针对每个测试用例执行多次)和tearDownClass函数(仅执行一次),用于清理测试资源。

注意事项:

1、在继承TestCase的类中,不应重写__init__()方法,以免干扰测试框架的内部机制。

2、只有以test开头的函数才会被unittest框架识别并执行,其他函数将被忽略。

3、如果需要使用setUpClass()和tearDownClass(),必须使用@classmethod装饰器进行修饰,否则框架无法正确调用。

测试生命周期与执行结果


# -*- encoding=utf-8 -*-

import unittest
class Demo1(unittest.TestCase):
  def setUp(self):
    print '调用 setup 函数'

  @classmethod
  def setUpClass(cls):
    print '调用 setupClass 函数'

  def tearDown(self):
    print '调用 tearDown 函数'
  @classmethod
  def tearDownClass(cls):
    print '调用 tearDownClass 函数'

  @staticmethod
  def test_add():
    print '3 + 5 = {}'.format(3 + 5)

  @staticmethod
  def test_sub():
    print '3 - 5 = {}'.format(3 - 5)


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

以下是运行上述基本测试用例后的典型输出结果:

调用 setupClass 函数

调用 setup 函数

3 + 5 = 8

调用 tearDown 函数

调用 setup 函数

3 - 5 = -2

调用 tearDown 函数

调用 tearDownClass 函数

Ran 2 tests in 0.012s

OK

使用TestSuite管理测试用例

除了自动运行,还可以通过TestSuite【测试组】手动添加测试用例来进行更灵活的测试控制。


# -*- encoding=utf-8 -*-


class Class1(object):
  def __init__(self):
    print '调用 Class1 初始化函数'
    self.name = '未定义姓名'
    self.age = '未定义年龄'

  def set_name(self, name):
    self.name = name

  def set_age(self, age):
    self.age = age

  def print_name(self):
    print 'Class1 的姓名是:{}'.format(self.name)

  def print_age(self):
    print 'Class1 的年龄是:{}'.format(self.age)


if __name__ == '__main__':
  pass

 

# -*- encoding=utf-8 -*-

import unittest

from Class1 import Class1


class CallClass1(unittest.TestCase):

  def setUp(self):
    self.class1 = Class1()
    pass

  def tearDown(self):
    self.class1 = None
    pass

  def test_set_name(self):
    self.class1.set_name('设置了名字')
    self.class1.print_name()

  def test_print_name(self):
    self.class1.print_name()


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

 

# -*- encoding=utf-8 -*-

import unittest
from Test_Demo2 import CallClass1

if __name__ == '__main__':
  testSuite = unittest.TestSuite()
  testSuite.addTest(CallClass1('test_set_name'))

  testSuite.addTests(
    [CallClass1('test_set_name'), CallClass1('test_print_name')])

  textTestRunner = unittest.TextTestRunner()
  textTestRunner.run(testSuite)

运行包含TestSuite的测试代码后,结果如下:

调用 Class1 初始化函数

Class1 的姓名是:设置了名字

调用 Class1 初始化函数

Class1 的姓名是:设置了名字

调用 Class1 初始化函数

Class1 的姓名是:未定义姓名

...

----------------------------------------------------------------------

Ran 3 tests in 0.000s

OK

Process finished with exit code 0

为了便于后续分析,可以将测试结果记录到txt文件中。

生成TXT与HTML测试报告


# -*- encoding=utf-8 -*-

import unittest
from Test_Demo2 import CallClass1

if __name__ == '__main__':
  testSuite = unittest.TestSuite()
  testSuite.addTest(CallClass1('test_set_name'))

  testSuite.addTests(
    [CallClass1('test_set_name'), CallClass1('test_print_name')])

  # textTestRunner = unittest.TextTestRunner()
  # textTestRunner.run(testSuite)

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

此外,还可以将测试结果导出为更易读的html文件报告。


# 将测试结果输出到测试报告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)

断言机制与错误处理

断言是单元测试的核心,用于验证代码行为是否符合预期。

当断言条件为真时,测试通过,并继续执行断言之后的代码(例如打印成功提示信息)。

若断言条件为假,则后续代码不再执行,并记录错误信息。在unittest的输出中,'F'代表断言失败(Failure),若捕获到程序异常,则标记为'E'(Error)。

补充说明:如果断言失败,当前测试函数(def)会立即停止运行,但框架会继续执行列表中后续的测试函数。

重要提示:切勿在try语句块中使用assert断言。因为assert失败时会抛出异常,如果将其包裹在try中,异常会被捕获,导致测试用例被错误地标记为通过,从而掩盖真实问题。

断言执行后的结果标识如下:

. 或 pass:表示测试通过。

F (False):表示断言未通过,测试失败。

E (Error):表示程序运行过程中发生了内部错误。

unittest支持自动查找当前目录下所有的测试用例(默认查找以test开头的.py文件,也可自定义配置)。

自动发现与运行测试用例


# -*- encoding=utf-8 -*-

import unittest
import os

if __name__ == '__main__':
  loader = unittest.defaultTestLoader.discover(os.getcwd())
  # tests = unittest.defaultTestLoader.discover(
  #   start_dir='.', # => 指定查找的目录
  #   pattern='test*.py' # => 指定查找规则
  # )
  runner = unittest.TextTestRunner()
  runner.run(loader)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。