用途
fix-flaky-test 用于处理非确定性测试(flaky test):有时通过、有时失败的测试,通常在 CI 负载下比本地更容易失败。该指南强调,偶发失败是系统真实信号,可能涉及顺序、时序、共享状态或资源泄漏,唯一可接受的解决方式是复现、命名不确定性类别、修复根因,并用循环运行同一测试来证明修复。
主要能力与规则
- 复现优先:在声称理解问题前先循环运行测试直到失败触发,通常 100 次,低频 flake 常需 500–1000 次;然后运行足够次数以信任观察到的失败率。若无法复现,应扩大条件(类 CI 负载、并行运行兄弟测试、固定或变化随机种子、推进时钟),而不是判定问题不存在。需要粘贴包含通过和失败的循环输出作为复现证据。若项目未在 AGENTS.md 中说明如何循环单个测试,应询问项目机制,不得猜测。
- 命名不确定性类别:类别包括时序/顺序、共享状态、网络/外部服务、随机性、时间/时钟、资源耗尽、环境。混合类别的 flake 应拆分为独立修复;一个声称覆盖两类的修复往往只是掩盖了其中一个。
- 在生产代码或测试设置中定位根因:断言只是信使,根因可能位于非确定性生产代码(未播种随机、未 mock 时间、竞态)、未隔离的 setup/teardown、并行测试框架或环境。
- 修复根因而非掩盖:注入时钟或种子、隔离共享状态(新鲜 fixture、作用域 teardown)、等待真实契约(稳定状态、发出的事件)而非 sleep、正确保留和释放争用资源。
- 用同一测试循环验证修复:在 flake 复现的条件下运行足够次数,每次通过,并粘贴输出。一次绿色仅证明失败率低于 100%,循环才是证明失败率为零的唯一证据。
- 在根因处留一行注释说明失败模式,便于后续读者识别。
- 若根因是真实生产缺陷(竞态、未处理 rejection、泄漏),本任务交付诊断和已稳定的测试作为回归守护,生产修复作为独立任务记录为 finding candidate,不捆绑。不得对自己的工作撰写 review 结果。
不接受的替代方案
文档明确列出若干诱惑及应做之事:重跑后通过不能算修复;加 sleep 不解决竞态;无法复现不等于无问题;放宽断言不能修复漂移;try/catch 吞掉信号等于另一种放宽;跳过测试只是带负责人和日期的隔离而非修复;只在 CI 复现应尽力复现 CI 条件或报告 Blocked;diff 看起来明显也不能替代循环输出。
适用场景与限制
适用于已存在且已被标记为 flaky 的测试稳定化。若测试在变更后 100% 失败,属于普通缺陷,应走 write-fix;编写新测试属于 write-testing。技能附带 references/task-template.md 工作笔记脚手架,包含 flake 类别、复现协议与证据、假设跟踪、修复证据和自审。文档未提供安装命令、收费、价格或具体平台要求。
自审门禁
完成任务前需确认:已粘贴复现循环输出,失败可见、失败率有测量、条件不比原始失败更容易;仅命名一个不确定性类别,混合 flake 已拆分;修复位于生产代码或测试设置的根因处,而非断言、sleep、超时上调、try/catch 或隔离;已粘贴修复循环输出,同一测试、相同条件、每次通过;在根因处有一行注释说明失败模式;生产侧根因已记录为 finding candidate 并以该测试作为回归守护;未对自己的工作发布 review 结果。