
Qwen Code 测试去抖动指南用 deflake 技能以最小修复稳定任意偶发测试【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读本指南围绕 Qwen Code 开源仓库中内置的deflakeAgent 技能.qwen/skills/deflake/SKILL.md展开它定义了一套处理同一个 commit 上先失败后通过的偶发flaky测试的标准化工作流只允许四种最小修复手段、禁止任何削弱断言的取巧行为并要求以重复运行证据收尾。读完本文你将掌握如何为偶发测试精确诊断其非确定性来源、在四种合法修复手段中挑选最小方案、严格遵守绝不弱化断言的硬性规则以及如何用vitest与仓库既有配置完成可验证的去抖动闭环。什么是 flaky 测试deflake 技能在什么场景下被触发偶发测试的典型签名deflake技能面向的是以deflake:开头的 issue其判定标准非常严格同一个 commit 上某个测试先被观察到失败随后在重跑时通过——这是偶发测试最确凿的特征签名即测试行为取决于运行时的非确定性因素如时序、机器负载、随机数或共享资源冲突而非代码逻辑本身的缺陷。issue 正文通常携带两类信息是去抖动工作的起点测试身份identity文件路径 测试名称完整标题例如describe › it的嵌套链失败签名failure signature例如Test timed out in 5000ms、Timed out waiting for …、顺序依赖的断言失败、依赖墙钟时间或随机数的取值。技能要求先完整阅读该测试在头脑中复现其非确定性产生的机制再从下面四类被允许的修复中挑选最小的那一个。技能在仓库中的定位从 CI 巡检到去抖动的完整链路在 Qwen Code 仓库中deflake并不是孤立存在的它与 .qwen/skills/ci-flaky-patrol/SKILL.md 形成闭环ci-flaky-patrol负责对一批过期的 PR CI 失败进行分类当它判定某个rerun的根因是测试本身的非确定性而非 ENOSPC、网络、runner 死亡等基础设施抖动时会在ci-flaky-decisions.json中产出flakyTest对象携带从日志中逐字摘录的失败file与name从而驱动后续环节开出deflake:修复任务。也就是说deflake技能正是这条CI 巡检 → 分类 → 去抖动流水线的执行端。四种唯一被允许的修复手段技能明确规定去抖动的全部修复空间只有以下四类且必须从中选择能消除非确定性的最小方案。1. 提高超时 / 轮询预算Raise a timeout / poll budget当一个测试在 CI 争用fully-mocked 或 I/O 密集而非性能测试下冲爆 vitest 默认 5 秒超时时可以给予更宽裕的逐测试testTimeout即it的第三个参数或者把测试内部固定轮询次数的轮询循环改为真实的墙钟时间预算——固定次数的setImmediate在毫秒级就耗尽会与真实 I/O 产生竞态。// 为单个测试提高超时上限只抬高天花板不触碰任何断言 it( extracts a large tarball under CI contention, async () { // ... }, 30_000, // 第三个参数该测试专属 testTimeout );仓库中与此对应的全局实践是按运行环境动态抬高超时。packages/core/vitest.config.ts 与 packages/cli/vitest.config.ts 都这样配置testTimeout: process.env[RUNNER_NAME]?.startsWith(ecs-qwen-) ? 60_000 : 15_000,配置注释明确写道自托管 CI runner 严重超额订阅I/O 或 WASM 加载型测试如 web-tree-sitter 惰性运行时、tar 解压纯粹因争用而冲爆 5 秒默认值并非逻辑错误断言仍然即时失败只是超时天花板变高。这正是技能中超时上浮只改变上限、不削弱任何断言原则的仓库级落地。2. 稳定时序 / 等待Stabilize timing / waiting把裸setTimeout/ 固定sleep替换为对真实条件的显式awaitvi.waitFor、已 resolve 的 Promise、事件让测试在条件真正成立时再继续而不是赌一个固定的时间窗口。在 Qwen Code 测试代码中vi.waitFor是等待异步条件的主流做法例如 packages/cli/src/acp-integration/acpAgent.test.tsawait vi.waitFor(() expect(ndJsonStream).toHaveBeenCalledOnce());此外对于惰性加载例如 WASM 运行时应提前预热把首次加载成本移出单个测试的时间预算在beforeAll中完成加载避免每个测试都被首载开销拖到超时边缘。3. 让随机性 / 时间变得确定Make randomness / time deterministic对依赖真实时钟或Math.random的取值通过以下方式钉死为 RNG 设置固定种子vi.useFakeTimers()接管定时器或 mockDate.now固定输入使结果不随真实时间漂移。在仓库中vi.useFakeTimers被广泛用于各类通道与桥接测试包括 packages/acp-bridge/src/bridge.test.ts、packages/acp-bridge/src/channel-liveness.test.ts、packages/channels/dingtalk/src/DingtalkAdapter.test.ts、packages/channels/telegram/src/TelegramAdapter.test.ts 等十余个包内的大量测试文件说明让时间确定化在该代码库中是一等公民的测试手法。注意vi.useFakeTimers()之后通常需要在测试末尾调用vi.useRealTimers()还原以免污染同文件内的其他测试。4. 隔离 / 串行化干扰Isolate / serialize interference当多个测试共享同一资源并相互碰撞时同名临时目录、固定端口、全局单例为每个测试分配独立的专属资源或在必要时将其串行化。典型做法是为临时目录追加测试名/随机后缀、使用可配置的端口分配、避免共享全局状态。硬性规则绝不允许隐藏抖动技能用一条Never清单划定了不可逾越的边界。以下行为一律禁止因为它们不是在修复抖动而是在掩盖它甚至可能掩盖真实的产品缺陷删除测试对测试使用skip/todo放宽断言、扩大期望值范围添加笼统的try/catch在断言外层套重试包装retry wrapper。若四种修复手段均不适用或失败看起来是真实的产品间歇性缺陷而非测试非确定性则必须停止操作在工作目录写入workdir/failure.md说明发现交由人类去抖动。变更边界的纪律Diff 最小化且局部化只改动被指名的测试及其所在文件的 helper不得顺手重构无关代码保留每一个断言与每一份输入原样超时上浮只改变天花板确定性修复只改变非确定性来源优先局部改动优先选择逐测试或逐文件变更除非同类问题明确遍布整个包——此时在对应包的vitest.config.ts中设置testTimeout可接受因为它只抬高上限、不削弱任何断言。这与仓库中 packages/core/vitest.config.ts 和 packages/cli/vitest.config.ts 的做法一致。验证重复运行 标准门禁修复完成后的验证分两层重复运行被指名的测试文件——在正确的包目录下多次执行npx vitest run file要求每次都必须通过跑一遍标准验证门禁——构建 / 类型检查 / lint / 被改动测试。如果无法让其确定性通过同样写入workdir/failure.md并停止。仓库根部的 vitest.config.ts 使用projects聚合了多个包的测试packages/cli、packages/core、packages/vscode-ide-companion、packages/sdk-typescript、packages/channels/*、integration-tests、scripts等因此在定位到具体包后应在该包目录内运行npx vitest run file以获得正确的解析环境若要跑跨包聚合可回到仓库根目录执行。npx vitest run file是 vitest 的单次运行模式非 watch适合在验证阶段连续执行多次以收集确定性证据。收尾产物PR 与双语 e2e 报告验证通过后按 .qwen/skills/prepare-pr/SKILL.md 准备 PR 标题与正文写入pr-title.txt与pr-body.md遵循 Conventional Commit 风格与仓库 PR 模板包含 Reviewer Test Plan、前后行为对比的 Evidence 等并书写双语workdir/e2e-report.md遵循 Shared Rules其中必须陈述三点抖动的机制flaky mechanism应用了四类修复中的哪一类、为什么重复运行的证据证明该测试现已确定性通过。这三点把修复结论与可复核证据绑定是去抖动工作区别于简单加超时的关键——reviewer 无需重新猜测修复意图直接按报告中的机制与证据复核即可。小结去抖动的判定路径整个技能的决策路径可以浓缩为确认签名——同一 commit 失败后通过携带失败签名通读测试在脑中复现非确定性机制从四类修复中挑最小方案抬高超时 / 稳定等待 / 确定化时间与随机 / 隔离与串行化遵守硬性规则绝不删除、跳过、放宽断言或加重试包装diff 保持局部重复运行被点名测试文件验证确定性再过构建 / 类型检查 / lint 门禁无法确定性修复或疑似真实产品缺陷时写failure.md并停止交给人类成功则产出 PR 元数据与双语e2e-report.md。这套方法论的价值在于它把修好一个偶发测试从碰运气加超时提升为先定位非确定性来源、再以断言保持assertion-preserving的最小变更消除它同时为 CI 上的每一条 flaky 失败留下可追溯、可复核的修复证据——这正是 Qwen Code 在 packages/core/vitest.config.ts、packages/cli/vitest.config.ts 等配置中体现的工程纪律也是 .qwen/skills/ci-flaky-patrol/SKILL.md 与 .qwen/skills/deflake/SKILL.md 构成闭环流水线的最终目标。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考