← 中文资源

简体中文版本

用重跑揭穿不稳定的测试

以打乱顺序与固定种子反复运行套件,按失败方差排名,只隔离被证实的惯犯。

阅读英文原文

目标

当红色构建被习惯性地重跑到变绿,测试套件就不再是证据而只是噪音。连跑三遍、统计失败方差、用种子加乱序复现,能把“感觉这测试偶尔挂”变成一份按优先级排名、有责任人、有过期时间的隔离清单,让真正的回归不再藏进十个已知不稳定测试的阴影里。

步骤要点

  1. 连续跑三遍套件并各存一份失败列表,先 diff 区分反复失败与偶发失败。
  2. 合并三份列表做 uniq -c 统计:计数为 3 的是真坏的测试要修,计数 1-2 的就是不稳定测试,按计数排优先级。
  3. 用 –sequence.shuffle 加不同 seed 复现单个不稳定测试,证明它依赖执行顺序或时序,而不是瞎猜。
  4. 隔离被证实的惯犯:显式配置排除或 @flaky 标记,每条写清 owner、expiry 与 reason,绝不静默删除。
  5. 单独跑隔离车道形成周报,某条测试连续两周稳定通过时凭绿色运行记录毕业回主套件。

排错提示

本地无法复现的多半是 CI 独有的共享状态或资源受限,抓日志与计时信息或在本地跑同一容器镜像复现环境;重跑到绿已是习惯就先把重试显式化,需要重试才过的构建记为失败并统计每周重试数,用指标把习惯变成修根因的压力;隔离清单只增不减就给每条加过期时间并路由到责任人,没有衰减机制的清单只是杂物抽屉。

适用边界

三遍运行只证明观测到的种子与顺序下的间歇性,更深的时序 bug 需要压力循环或注入延迟;隔离会把信号挡在主套件外,周报必须如实汇报隔离车道的通过率。

代码示例

# Three runs, three failure lists
for i in 1 2 3; do
  npx vitest run --reporter=json > run-$i.json || true
done

# Which tests fail sometimes, and which always?
cat fail-1.txt fail-2.txt fail-3.txt | sort | uniq -c
# 3  checkout/applies-coupon      -> genuinely broken
# 1  search/debounces-input       -> flaky (order/time dependent)
# 2  auth/refresh-token           -> flaky (clock skew)

# Reproduce one offender deterministically
npx vitest run --sequence.shuffle --sequence.seed=42