专项练习 · 8 分钟阅读

Python assert 练习:用断言测试函数

断言是你对程序做出的声明。声明为假时,Python 会抛出 AssertionError 并停止当前路径。只要不把它和输入校验混为一谈,assert 就是很好的教学和测试工具。

写出预期结果

assert add(2, 3) == 5 把预期变成可执行代码。实现变化时,检查会在确切的行失败。每个断言只关注一个行为,失败原因就更容易诊断。

def add(a, b):
    return a + b
assert add(2, 3) == 5
print("ok")

一个清楚的声明

加上说明差距的消息

断言失败时会显示逗号后的消息。写清预期值,必要时也写实际输入。避免只写 failed 之类的消息,它只是重复异常已经表达的内容。

def double(n):
    return n * 2
try:
    assert double(3) == 7, "double(3) should be 6"
except AssertionError as error:
    print(error)

有用的失败消息

捕获失败来研究它

AssertionError 是普通异常,小示例可以捕获它并打印消息。真实测试中应让失败传给测试运行器。把失败藏起来,就失去了检查的意义。

try:
    assert 1 == 2, "one is not two"
except AssertionError as error:
    print(error)

查看失败,而不是掩盖它

同时测试正常值和边界值

对 2 和 3 正常的函数,遇到 0、空列表或负数仍可能出错。每组小测试至少加一个边界情况。断言让这些情况成为代码的一部分,而不是一句注释。

def total(values):
    return sum(values)
assert total([]) == 0
assert total([1, 2, 3]) == 6
print("boundary and normal cases pass")

加入一个边界情况

知道 assert 不适合什么

不要用 assert 校验密码、权限或用户输入。Python 的 -O 参数会移除 assert 语句,用这种方式写的安全检查可能直接消失。校验时应抛出 ValueError 或自定义异常。

def positive(n):
    if n <= 0:
        raise ValueError("n must be positive")
    return n
print(positive(3))

校验应该写在 if 里

你的练习清单

常见问题

assert 可以被禁用吗?

可以。用 -O 运行 Python 会移除 assert 语句,所以不能用它保护安全或必需校验。

assert 抛出什么异常?

AssertionError。可选消息会成为异常文本。

每个函数都应该写断言吗?

不需要。把断言放在假设重要、失败必须明显的地方,尤其是测试和内部辅助函数。

练习断言

12 道题,覆盖 assert、消息、AssertionError、边界情况和输入校验。

打开练习

继续阅读: