测试代码
写完代码后需要验证它是否按预期工作。手动测试只能覆盖有限的情况,而且容易遗漏。自动化测试(单元测试)让程序帮你检查,每次修改代码后都能快速验证有没有引入新 bug。
为什么要写测试
- 早发现 bug:在开发阶段就发现问题,修复成本低
- 便于重构:改代码时有测试兜底,心里更有底
- 文档作用:测试用例展示了函数应该怎么用、期望什么结果
- 团队协作:别人改你的代码时,测试能防止误改
unittest 模块
Python 标准库自带 unittest 测试框架。基本用法:
import unittest
def add(a, b):
"""两数相加"""
return a + b
class TestMath(unittest.TestCase):
"""测试数学运算"""
def test_add_positive(self):
"""测试两个正数相加"""
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
"""测试包含负数的情况"""
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(-2, -3), -5)
if __name__ == "__main__":
unittest.main()
运行后输出:
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
每个 test_ 开头的方法就是一个测试用例。unittest.TestCase 提供了很多断言方法:
| 方法 | 用途 |
|---|---|
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | x 为真 |
assertFalse(x) | x 为假 |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertIsNone(x) | x is None |
assertRaises(Error) | 预期抛出异常 |
测试类
测试自定义类的功能:
class Member:
def __init__(self, name, role):
self.name = name
self.role = role
self.projects = []
def join_project(self, project):
self.projects.append(project)
class TestMember(unittest.TestCase):
def setUp(self):
"""每个测试方法运行前都会执行"""
self.member = Member("Alice", "前端")
def test_init(self):
self.assertEqual(self.member.name, "Alice")
self.assertEqual(self.member.role, "前端")
self.assertEqual(self.member.projects, [])
def test_join_project(self):
self.member.join_project("官网重构")
self.assertIn("官网重构", self.member.projects)
self.assertEqual(len(self.member.projects), 1)
if __name__ == "__main__":
unittest.main()
setUp() 方法很适合创建测试需要的数据,避免每个测试方法里重复写初始化代码。
测试失败的场景
有时候函数应该在特定条件下抛出异常。用 assertRaises 测试这种情况:
def divide(a, b):
if b == 0:
raise ValueError("除数不能为零")
return a / b
class TestDivide(unittest.TestCase):
def test_normal(self):
self.assertEqual(divide(10, 2), 5)
def test_divide_by_zero(self):
with self.assertRaises(ValueError):
divide(10, 0)
测试策略
- 测试正常情况:输入合法数据,验证输出正确
- 测试边界情况:空值、最大值、最小值
- 测试异常情况:错误输入是否抛出合适的异常
- 一个测试只验证一件事:测试失败时能快速定位问题
运行测试
命令行运行:
python -m unittest test_module
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
也可以用第三方工具如 pytest,语法更简洁:
pip install pytest
pytest test_module.py
写测试确实要花额外时间,但从长远看能省下大量调试和返工的时间。刚开始可能觉得麻烦,养成习惯后会觉得不写测试反而心里不踏实。