Skip to main content

测试代码

写完代码后需要验证它是否按预期工作。手动测试只能覆盖有限的情况,而且容易遗漏。自动化测试(单元测试)让程序帮你检查,每次修改代码后都能快速验证有没有引入新 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

写测试确实要花额外时间,但从长远看能省下大量调试和返工的时间。刚开始可能觉得麻烦,养成习惯后会觉得不写测试反而心里不踏实。