3.4 dsh-ci-test-reliability:测试与 flaky 治理

它是什么

dsh-ci-test-reliability 的官方描述:设计、评审并诊断 DeepSeek Harness 的测试与 fixture。

约 9442 字节,另带一份专门的参考资料 ci-flake-diagnosis.md(约 5346 字节)。后者这个名字说明了一切:团队专门为“不稳定测试”写了诊断手册。

多数团队对 flaky 测试的态度是“重跑一下就好了”,dsh 团队的态度是给它写诊断流程、写进技能。这个差别就是这个技能存在的理由。

flaky 测试为什么值得单独治理

一个偶发失败的测试比一个稳定失败的测试危害大得多:

稳定失败 偶发失败(flaky)
可见性 高,立刻发现 低,时有时无
信任侵蚀 无(大家都知道它坏) 严重,团队开始习惯性重跑
真实 bug 漏网 不会 会,因为失败被当成噪声
修复动力 有 弱,“再跑一次就好了”

最后一行是最危险的。一旦团队形成“红了就重跑”的条件反射,CI 就失去了守门意义——更糟的是,这个反射会自我强化:重跑越多,失败越被视为噪声;越被视为噪声,越没人去修;越没人修,重跑越多。几周之后,没人说得清 CI 到底是绿的还是只是“跑第二次才绿的”。

稳定失败是明疮,剜掉就行;flaky 是暗伤,它让整套质量信号失真。治理 flaky 本质上是在修复团队的判断能力,而不是修一个测试。

flaky 根因速查表

按一般经验,诊断手册要归类的根因通常离不开下面四类。看到 flaky 先往这几类上靠,比盲目重跑快得多:

根因 典型表现 排查抓手
时间依赖 固定 sleep 后断言、依赖“现在”的时刻 把相对等待改成条件等待;用注入的时钟
顺序依赖 单独跑过、批量跑挂;换执行顺序就挂 让测试不依赖全局执行次序;用随机种子复现
共享状态 测试之间偷偷传数据,上一个改了下一个的环境 每个用例独立建库 / 独立目录;禁止模块级可变单例
外部依赖 真连网络、真调时钟、真打外部服务 用 mock / fixture 切断外部;对集成测试单独标记
并发竞态 偶发超时、偶发读到旧值 缩小临界区;用确定性锁顺序;跑并发多次复现

这个表的用法是:拿到一个 flaky,先判断它落在哪一类,再去对应的排查抓手里找复现办法。顺序错了,会在错误的方向上花一下午。

三层覆盖

从“主技能 + 诊断参考”的结构看,这类技能通常分三层:

设计层:

  • 测试该测什么(行为而非实现)
  • fixture 怎么组织才能避免相互污染
  • 并发测试如何隔离

评审层:

  • 新测试是否可失败(mutation 思维)
  • 是否依赖执行顺序
  • 是否有隐藏的时间依赖

诊断层(ci-flake-diagnosis.md):

  • 常见 flaky 根因分类
  • 复现策略
  • 修复优先级判定

三层的顺序有讲究:设计层决定测试“生下来”稳不稳,评审层决定新测试“进门”时过不过关,诊断层决定存量 flaky 怎么清。只做诊断不做设计,就是永远在救火;三层都做,火才会越来越少。

一条最小可复现的玩法

把诊断手册搬回自己项目时,最该保留的是“复现优先”的纪律。一个可落地的做法是给测试加一个循环复现开关:

复现 flaky 的步骤:
1. 固定随机种子(不让顺序每天变)
2. 同一用例连续跑 N 次(N=20~50),记录失败次数
3. 失败率 > 0 但 < 100% → 确认是 flaky,进入诊断表
4. 修复后重复第 2 步,失败率必须降到 0 才算闭合

没有第 4 步的“修复后复跑”,所谓修复只是运气——下一次 CI 它还会红,只是你以为修好了。

三条立即可用的原则

即使不装这个技能,下面三条也值得记住:

原则一:失败必须可复现。 不能稳定复现的失败不许标记为“已修复”。实操上,这意味着修复前先找到复现路径(固定种子、固定顺序、循环跑 N 次),修复后要能演示“以前红的现在不红了”。没有这个闭环,所谓修复只是运气。

原则二:不许无条件重跑。 重跑必须留下记录,让 flaky 率可见。没有重跑计数,你永远不知道自己的 CI 有多少比例是“跑第二次才绿的”——这个数字本身就是团队最该看的健康指标之一。

原则三:新测试先证明会失败。 写测试后故意破坏实现,确认它变红,再恢复。这一步能挡掉大量“永远通过”的假测试:断言写松了、fixture 建错了、路径根本没覆盖到,都会在这一步现形。花三十秒换一个真测试,是测试工程里性价比最高的一笔买卖。

和另外两个技能的关系

dsh-pre-push-checks(3.3 节)负责在推送前跑本地关键检查,其中就包含“相关测试是否通过”;本技能负责让这些测试本身值得信任。一个管“跑了没有”,一个管“跑的结果能不能信”。两件事都做到位,CI 才真正是守门人而不是噪音源。

你要不要装

你的情况 建议
CI 经常“红了又绿” 强烈建议,先读诊断手册
测试偶发超时 建议
项目还很小、无 CI 不必

小结

  • dsh-ci-test-reliability 覆盖测试设计、评审与诊断,约 9442 字节,附带约 5346 字节的 flaky 诊断手册。
  • flaky 测试比稳定失败更危险,因为它侵蚀团队对 CI 的信任。
  • 三层覆盖:设计层、评审层、诊断层。
  • 三条原则:失败可复现、禁止无条件重跑、新测试先证明会失败。

延伸阅读