首页/开发/代码质量与评审速查/评审时如何对待 flaky 测试
代码评审64 条

评审时如何对待 flaky 测试

不稳定的测试会侵蚀信任:评审新增或修改测试时,检查时间依赖、随机数据、共享状态与外部依赖等常见不稳定来源。

flaky 测试为什么要单独对待

不稳定测试(flaky test)指同一份代码在相同环境下时通时不过。它最大的损失不是某一次失败,而是信任被侵蚀——红了就重跑变成习惯,真正的失败也会被当成噪声忽略。评审新增或修改测试时,值得专门看一眼常见的不稳定来源。

基本信息

表现同一提交上时通过时失败,重跑往往又变绿
常见来源时间依赖、随机数据、共享状态、外部依赖、并行竞争
评审动作识别来源并要求修复,而不是靠重试掩盖
处置顺序先定位不稳定来源,再决定修测试还是修被测代码

典型使用场景

  • 测试里有 sleep 或真实时钟:改成可注入的时钟,不依赖执行速度
  • 用例使用随机数据:固定随机种子,失败时输出可复现的信息
  • 用例之间共享数据库或全局状态:改为各自创建并清理数据
  • 依赖外部网络与第三方服务:用桩件或本地假实现替代
  • CI 上比本地更容易失败:多为并行执行与资源竞争,需要隔离

不稳定来源与修复方向

来源典型写法修复方向
时间依赖先 sleep 一秒再断言注入可控时钟,或等待明确条件而不是等待时间
随机数据随机生成的手机号与昵称固定种子,并把种子打进失败日志
共享状态多个用例共用同一测试用户每个用例创建并清理自己的数据
外部依赖直接调用真实的支付网关改用桩件或本地假实现,契约另行验证
超时过短默认超时在慢机器上必然失败按最慢环境的实际耗时给足超时

本地复现与定位

本地复现与定位
# 反复运行同一个用例,估一下失败率
for i in $(seq 1 20); do pytest tests/test_order.py::test_retry -q || echo "failed at $i"; done
pytest -p no:randomly tests/   # 关闭随机顺序插件,验证是否与执行顺序相关
pytest --tb=long -x tests/test_order.py   # 保留完整堆栈
# CI 侧开启失败日志与截图上传,便于比对偶发失败的现场
用重试掩盖不稳定测试:失败率下降但根因仍在,还会持续掩盖真实存在的偶发缺陷。
给已知的不稳定测试打标签并记录失败率,比口口相传可靠:治理清单有了数据才好排优先级。

易错点

  • 重试三次当修复:不稳定源仍在,同时掩盖真实缺陷
  • 测试里大量固定等待:机器一慢就失败,套件总时长也白白增加
  • 用例共享数据库状态:执行顺序一变结果就变,排查成本极高
  • 把偶发失败一律归为环境问题:同类缺陷会在发布后以线上故障的形式出现

数据来源与参考

  • Google Testing Blog(flaky 测试治理文章)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌