1. 为纯函数编写首个单元测试

为纯函数编写首个单元测试 学习卡片

任务:给一个纯加法函数补上第一组测试

本节要测试的对象是一个无副作用的纯函数 add(a, b):它只依赖入参、只返回结果,不读写外部状态。测试框架选用 Python 标准库自带的 unittest,无需额外安装即可运行。我们要完成三件事:写出被测函数、用断言验证正常输入、用断言验证边界输入,并理解一个测试用例由“准备数据 → 调用被测函数 → 断言结果”构成。

被测函数与测试文件

把被测函数和测试代码放在同一目录下,先建立被测模块 calc.py:

# calc.py
def add(a, b):
    """返回 a 与 b 的和,无副作用。"""
    return a + b

再建立测试文件 test_calc.py。测试类必须继承 unittest.TestCase,每个测试方法名以 test_ 开头,框架才会自动发现并执行它:

# test_calc.py
import unittest
from calc import add

class TestAdd(unittest.TestCase):

    def test_add_two_positive_integers(self):
        # 正常输入:两个正整数
        result = add(2, 3)
        self.assertEqual(result, 5)

    def test_add_positive_and_negative(self):
        # 正常输入:一正一负
        result = add(10, -4)
        self.assertEqual(result, 6)

    def test_add_with_zero(self):
        # 边界输入:加数为 0
        self.assertEqual(add(0, 7), 7)
        self.assertEqual(add(7, 0), 7)

    def test_add_two_zeros(self):
        # 边界输入:两个 0
        self.assertEqual(add(0, 0), 0)

    def test_add_floats(self):
        # 正常输入:浮点数
        self.assertAlmostEqual(add(0.1, 0.2), 0.3, places=7)

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

测试用例的基本结构

每个 test_ 方法内部都遵循同一套三段式结构,这是单元测试最核心的骨架:

  • Arrange(准备):确定输入值,例如 a = 2, b = 3。
  • Act(执行):调用被测函数,例如 result = add(2, 3)。
  • Assert(断言):用断言方法比对实际值与期望值,例如 self.assertEqual(result, 5)。

断言是测试的判定点:断言通过,该用例记为通过;断言失败,框架抛出 AssertionError 并标记该用例失败。常用断言方法如下表:

断言方法判定含义本例用途
assertEqual(a, b)a 等于 b整数相加结果比对
assertNotEqual(a, b)a 不等于 b验证错误结果不被误判为通过
assertAlmostEqual(a, b, places=n)四舍五入到 n 位后相等浮点数相加结果比对
assertTrue(x) / assertFalse(x)x 为真 / 为假布尔型结果判定
浮点数不要直接用 assertEqual 比较,因为 0.1 + 0.2 在二进制浮点下并不精确等于 0.3,应使用 assertAlmostEqual 并指定精度。

运行与结果判读

在测试文件所在目录执行:

python -m unittest test_calc.py -v

-v 会逐条打印用例名与结果。全部通过时输出形如 Ran 5 tests ... OK;若某条断言失败,输出会指出失败的用例名、断言行以及 AssertionError 的实际值与期望值差异,据此定位是被测函数逻辑错误还是期望值写错。

add(a, b) 测试用例结构与断言判定 被测纯函数 add(a, b) 无副作用 · 只依赖入参 正常输入 (2,3) (10,-4) (0.1,0.2) 边界输入 (0,7) (7,0) (0,0) 用例三段式 Arrange 准备输入 Act 调用 add Assert 断言比对 断言判定 assertEqual / assertAlmostEqual 通过 实际值 == 期望值 失败 AssertionError 定位差异

可执行检查清单

检查项通过标准
测试类继承 unittest.TestCase类定义形如 class TestAdd(unittest.TestCase)
测试方法命名所有方法以 test_ 开头,框架能自动发现
正常输入覆盖至少包含正整数、一正一负、浮点数三类
边界输入覆盖至少包含加数为 0、两个 0 两类
浮点断言方式使用 assertAlmostEqual 而非 assertEqual
运行结果python -m unittest test_calc.py -v 输出 OK
若把 add 改成 return a - b 再运行,test_add_two_positive_integers 会失败并报 AssertionError: -1 != 5。这说明断言确实在检验函数行为,而不是走过场——测试通过的前提是断言真的能失败。