TT Lab
开始
学习 学习路径 课程

测试工具实战

用边界值测试发现真实缺陷:设计原理

在 TT Lab 中继续学习

一句话总结

好的边界值测试能把“看似合理却有错的实现”与正确的实现区分开来。

为什么需要它

即使是只有十行的费用计算器,只要有一个边界写错,就会对每一笔订单收取错误的金额。 只确认 price(3) 等于 1050 的测试,即使折扣阈值中的 >= 被改成 >,也照样通过。 与其重复测试许多中间值,不如选取条件发生变化的“紧邻之前、恰好那一点、紧邻之后”。 本实验不读取覆盖率报告中的数字。先在正确代码上运行你写的测试,再在条件写错了一处的代码上重新运行,从而实际观察两者的差异。

工作原理

输入 契约
整数 0 0 韩元
整数 1–9 每件 350 韩元
整数 10–100 全部数量按每件 300 韩元
范围之外的整数 ValueError
非整数的值、bool TypeError

折扣不是只对第 10 件之后的部分生效的累进方式,而是改变全部数量的单价。 如果没有这句话就去写测试,就会围绕不同的策略争论哪个实现才是对的。 测试名称和预期金额应当体现策略的含义。

在现场相遇的样子

在 Python 中,bool 是 int 的子类,所以 isinstance(True, int) 为真。业务上能否把数量 True 当作 1 件来接受,语言并没有规定。本契约明确拒绝这种输入,因此把 bool 单独列为反例。另一方面,如果去检查实现中的变量名或 if 语句的数量,就会把行为不变的重构误认为 bug。应当观察的是输入、结果和异常。

下一项实验要做什么

依次累积八个测试:0、1、折扣之前、边界、折扣之后、最大值、负数、错误类型。 如果在正确实现上失败,先修正测试的预期值。即使在有缺陷的实现上失败,语法错误或导入错误也不算检出缺陷。必须是已执行测试中的 assertion 失败,或者出现与预期不同的运行时异常。能抓住所有这些缺陷样本,只是对所验证契约的证据,而不是“所有 bug 都不存在”的证明。

参考:pytest 入门