用边界值测试发现真实缺陷
目标
对费用函数的正确实现和八种有缺陷的实现,运行同一组 pytest 测试。
为什么重要
一次正常请求成功,并不能保证边界值和故障恢复也没有问题。本实验先为每个函数的契约编写小型实现或测试,再通过真实运行把它们串起来。评分不会只看代码是否存在或报告中的措辞,而是检查结果、异常和保存的状态。请保留前面步骤的代码,继续进行下一步。
步骤
- 在
/root/work/test-boundaries-lab/test_service.py中编写 pytest 测试,断言 price(0) 恰好为 0。只调用函数,或只检查结果是否为 int,都不够。第一次准备使用下面的命令。
mkdir -p /root/work/test-boundaries-lab
cp /opt/fixtures/practice_depth/test-boundaries-lab/* /root/work/test-boundaries-lab/
cd /root/work/test-boundaries-lab
- 在
/root/work/test-boundaries-lab/test_service.py中测试 price(1) 的金额是否为 350。保留原有的 0 件测试。 - 在
/root/work/test-boundaries-lab/test_service.py中测试 price(9) 是否为 3150。必须能检出从 9 件起就错误打折的实现。 - 在
/root/work/test-boundaries-lab/test_service.py中测试 price(10) 是否为 3000。用它抓住“10 件时不打折”的 > 条件错误。 - 在
/root/work/test-boundaries-lab/test_service.py中测试 price(11) 是否为 3300。用它检出把整个折扣区间固定返回 3000 韩元的实现。 - 在
/root/work/test-boundaries-lab/test_service.py中用 pytest.raises 确认 price(100) 为 30000,且 price(101) 抛出 ValueError。 - 在
/root/work/test-boundaries-lab/test_service.py中测试 price(-1) 是否抛出 ValueError。不要把返回负数费用当作正常处理。 - 在
/root/work/test-boundaries-lab/test_service.py中添加参数化测试,确认 True、False、1.0、'1'、None 全部抛出 TypeError。尤其要抓住把 bool 当作 int 接受的缺陷。
参考
- 软件包已安装在镜像中,不需要联网,也不需要 pip install。
- 准备阶段的复制只做一次。再次复制会使工作文件恢复初始状态。
/root/work/test-boundaries-lab/service.py是第一次准备时复制过来的、用于本地运行的提供代码。不要修改它,也不要用示例代码覆盖它,只编写test_service.py。- 测试要用
from service import ...导入提供的函数。评分会把测试单独复制到另一个临时目录,在正确实现和有缺陷的实现上运行。每一步都必须在实际运行测试时抓住对应的缺陷,而在正确代码上,已运行的测试必须全部通过。收集错误、导入错误和被强制终止都不算检出。不要依赖外部文件或网络。 - 每一步的评分都在 45 秒内执行。不要写出无限循环或真实等待。
拦住空订单的最低费用
在 /root/work/test-boundaries-lab/test_service.py 中编写 pytest 测试,断言 price(0) 恰好为 0。只调用函数,或只检查结果是否为 int,都不够。第一次准备使用下面的命令。
mkdir -p /root/work/test-boundaries-lab
cp /opt/fixtures/practice_depth/test-boundaries-lab/* /root/work/test-boundaries-lab/
cd /root/work/test-boundaries-lab
想一想那种“连空订单也收取 350 韩元”的缺陷。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/01-contract.sh 直接复现。保存文件后再运行一次。
确认最小的有效数量
在 /root/work/test-boundaries-lab/test_service.py 中测试 price(1) 的金额是否为 350。保留原有的 0 件测试。
只检查“价格为正数”,会放过收取 400 韩元的 bug。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/02-contract.sh 直接复现。保存文件后再运行一次。
抓住折扣之前的边界
在 /root/work/test-boundaries-lab/test_service.py 中测试 price(9) 是否为 3150。必须能检出从 9 件起就错误打折的实现。
折扣开始之前的那个值,与普通的中间值起的作用不同。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/03-contract.sh 直接复现。保存文件后再运行一次。
包含折扣的起点
在 /root/work/test-boundaries-lab/test_service.py 中测试 price(10) 是否为 3000。用它抓住“10 件时不打折”的 > 条件错误。
重新读一遍策略表,看看这个条件是否应当在边界上为真。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/04-contract.sh 直接复现。保存文件后再运行一次。
不要把折扣金额当成常量
在 /root/work/test-boundaries-lab/test_service.py 中测试 price(11) 是否为 3300。用它检出把整个折扣区间固定返回 3000 韩元的实现。
只检查边界上的一个点,折扣区间的斜率即使错了也发现不了。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/05-contract.sh 直接复现。保存文件后再运行一次。
同时验证上限的内外两侧
在 /root/work/test-boundaries-lab/test_service.py 中用 pytest.raises 确认 price(100) 为 30000,且 price(101) 抛出 ValueError。
把最大的合法值和紧随其后的非法值当作一对来处理。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/06-contract.sh 直接复现。保存文件后再运行一次。
不要把负数输入变成成功
在 /root/work/test-boundaries-lab/test_service.py 中测试 price(-1) 是否抛出 ValueError。不要把返回负数费用当作正常处理。
如果在 try/except 里什么都不做,即使没有抛出异常,测试也可能通过。请使用 pytest.raises。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/07-contract.sh 直接复现。保存文件后再运行一次。
拒绝 bool 和形似数字的字符串
在 /root/work/test-boundaries-lab/test_service.py 中添加参数化测试,确认 True、False、1.0、'1'、None 全部抛出 TypeError。尤其要抓住把 bool 当作 int 接受的缺陷。
要包含能体现 type(x) 与 isinstance(x, int) 差异的输入。测试必须调用公开函数,而不是实现源码。
评分可以用 bash /opt/lab/checks/test-boundaries-lab/08-contract.sh 直接复现。保存文件后再运行一次。