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

测试工具实战

隔离测试失败路径与副作用:设计原理

在 TT Lab 中继续学习

一句话总结

故障测试不仅要观察最终的返回值,还要观察调用次数、等待时间,乃至文件状态。

为什么需要它

短暂断开的连接可以通过重试恢复,但错误的输入即使反复发送同一个请求也无法修好。如果把这两类错误都用 except Exception 一并处理,即使返回了成功响应,也会产生隐藏的重复调用和不必要的等待。只有无需真的切断外部服务器、也无需一次等待好几秒就能测试失败路径,开发者才会每次都运行测试。

工作原理

fetch(send, sleep, cache) 会调用作为参数传入的 send,并且只对 TimeoutError 重试。总调用次数最多 3 次,第一次失败后把 0.1 秒、第二次失败后把 0.2 秒传给 sleep。第三次失败时不再等待,直接抛出异常。ValueError 之类的永久性错误会立即向上传播。成功得到的字符串会以 UTF-8 写入类型为 pathlib.Path 的 cache,然后返回。即使保存本身失败,也不会隐藏错误。

성공 → 파일 저장 → 반환
시간 초과 → 시도 남음? → 대기 → 재호출
           └─ 없음 → 예외, 기존 파일 그대로
영구 오류 → 즉시 예외

在现场相遇的样子

假的 send 会把调用记录留在列表里,并按既定顺序返回错误和值。假的 sleep 只记录延迟值。tmp_path 为每个测试提供不同的目录,因此上一个测试留下的缓存无法让下一个测试蒙混过关。保留已有缓存的契约针对的是网络失败。单纯的 write_text 无法对写入过程中的磁盘故障提供原子性保护,所以不把这个实现称为原子文件替换。

下一项实验要做什么

分别验证:成功、短暂失败后恢复、重试次数耗尽、永久性错误、等待序列、成功时保存、失败时保留、保存错误。不能假设在 root 环境下仅靠 chmod 就能造成写入失败。应当选择对环境依赖更小的失败条件,例如让程序把文件内容写入一个目录。评分会把同一组测试分别在正确实现和有缺陷的实现上运行,仅凭报告中的措辞或声明 mock 调用无法通过。

参考:pytest tmp_path