00357 🧪 Python `unittest` 单元测试框架教程


前言

下面是一个关于 Python 的 unittest 单元测试框架的 详细教程,适合初学者逐步入门,也包含了一些进阶用法,帮助你在项目中高效使用 unittest

官方文档地址:https://docs.python.org/zh-cn/3.13/library/unittest.html


📝 目录

  1. 什么是单元测试?
  2. 为什么使用 unittest
  3. 基本使用方式
  4. 断言方法
  5. 测试用例组织
  6. 测试夹具:setUp()tearDown()
  7. 测试套件与运行方式
  8. Mock 模拟对象(高级)
  9. 实战示例
  10. 小结

1️⃣ 什么是单元测试?

单元测试(Unit Test) 是指对软件中的最小可测试单元进行验证的测试活动。通常指的是函数或类的方法。


2️⃣ 为什么使用 unittest

Python 的 unittest 是标准库内置的测试框架,具有以下优点:

  • 类似于 Java 的 JUnit,功能全面
  • 无需额外安装
  • 支持测试夹具、测试套件、断言等
  • 可以集成到 CI/CD 工具中

3️⃣ 基本使用方式

# calculator.py
def add(x, y):
    return x + y

def divide(x, y):
    return x / y
# test_calculator.py
import unittest
from calculator import add, divide

class TestCalculator(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(2, 3), 5)
        self.assertEqual(add(-1, 1), 0)

    def test_divide(self):
        self.assertEqual(divide(10, 2), 5)
        with self.assertRaises(ZeroDivisionError):
            divide(10, 0)

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

🟡 运行方法:

python test_calculator.py

输出:

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

4️⃣ 常用断言方法

方法 用途
assertEqual(a, b) 断言 a == b
assertNotEqual(a, b) 断言 a != b
assertTrue(x) 断言 x 为 True
assertFalse(x) 断言 x 为 False
assertIs(a, b) 断言 a is b
assertIsNone(x) 断言 x is None
assertIn(a, b) 断言 a in b
assertRaises(Exception) 断言抛出异常

5️⃣ 测试用例组织结构

建议使用以下结构组织测试文件:

project/
├── calculator.py
└── tests/
    └── test_calculator.py

可以批量运行:

python -m unittest discover -s tests

6️⃣ 测试夹具(Fixtures)

setUp()tearDown() 是在每个测试方法前后自动执行的:

class TestWithSetup(unittest.TestCase):
    
    def setUp(self):
        print("准备环境")

    def tearDown(self):
        print("清理环境")

    def test_example(self):
        self.assertEqual(1 + 1, 2)

运行结果:

准备环境
清理环境
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

还可以使用:

  • setUpClass(cls):整个类运行前运行(类方法)
  • tearDownClass(cls):整个类运行后运行

7️⃣ 测试套件(Test Suite)

你可以将多个测试类组合成套件一起运行:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestCalculator('test_add'))
    suite.addTest(TestCalculator('test_divide'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

8️⃣ Mock(模拟对象)

有时候你不希望真的调用外部依赖(比如数据库、API),就可以使用 unittest.mock

from unittest.mock import Mock

def get_price(api_client):
    return api_client.get_price()

def test_get_price():
    mock_api = Mock()
    mock_api.get_price.return_value = 100
    assert get_price(mock_api) == 100

9️⃣ 实战示例:测试一个类

# bank.py
class BankAccount:
    def __init__(self, balance=0):
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError("Insufficient funds")
        self.balance -= amount
# test_bank.py
import unittest
from bank import BankAccount

class TestBankAccount(unittest.TestCase):

    def setUp(self):
        self.acc = BankAccount(100)

    def test_deposit(self):
        self.acc.deposit(50)
        self.assertEqual(self.acc.balance, 150)

    def test_withdraw_valid(self):
        self.acc.withdraw(30)
        self.assertEqual(self.acc.balance, 70)

    def test_withdraw_insufficient(self):
        with self.assertRaises(ValueError):
            self.acc.withdraw(200)

🔟 小结

内容 说明
基本结构 创建类继承自 unittest.TestCase
运行测试 直接运行 .py 文件或使用 unittest discover
常用断言 assertEqual, assertRaises
夹具方法 setUp, tearDown
模拟对象 使用 unittest.mock 模拟外部依赖
高级功能 测试套件、跳过测试、参数化

结语

第三百五十八篇博文写完,开心!!!!

今天,也是充满希望的一天。


文章作者: LuYF-Lemon-love
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LuYF-Lemon-love !
  目录