Repository navigation
fix(cli): stop review test-efficacy tests depending on ambient tmpdir vitest - #8537
Conversation
… vitest Two tests failed on hosts where vitest resolves up-tree from os.tmpdir() (observed on self-hosted CI where a node_modules above TMPDIR provides one): findVitestBin's "cannot be resolved" case never threw, and runControlMutant's "cannot run" case executed the probe for real instead of throwing. Make the failure conditions host-deterministic while keeping every assertion: findVitestBin accepts an injected resolver (default unchanged) so the MODULE_NOT_FOUND case is forced directly, and the runControlMutant test plants a shadow vitest whose exports hide package.json, which wins resolution from any ancestor install and makes the run fail deterministically.
E2E Report — deflake review test-efficacy testsFlaky mechanism
Both assumed Which fix was applied and whyAllowed-fix class 4 (isolate/serialize interference): remove the dependence on ambient filesystem state, preserving every assertion verbatim.
No assertion was weakened, skipped, or deleted; the production call path is byte-for-byte the default. Repeated-run evidenceA/B reproduction harness on macOS:
中文说明失败机制
修复方式断言逐字保留,消除对环境文件系统状态的依赖:
未弱化、跳过或删除任何断言;生产调用路径与默认值完全一致。 重复运行证据macOS 本地 A/B 复现:以 |
Code Review — #8537Verdict: LGTM, approve with two minor suggestions. I reproduced the CI condition and verified every claim in the PR body independently. What it doesTwo tests in Verification I ranBuilt the fake-TMPDIR harness from the test plan (
Mutation check — the reworked test still has teeth. I broke the production invariant it guards, moving the restore in const __v = perFile.some((r) => r.verdict === 'gated');
writeFileSync(abs, original, 'utf8');
return __v;
} finally { /* no longer survives the throw path */ }→ Production path is untouched. Convention fit. The optional-parameter seam matches what this file already does — Side benefit worth noting: the reworked test 2 now throws before any spawn, dropping from ~604ms (it was actually executing a real vitest run under the ambient-vitest condition) to ~10ms. Suggestions1. Pin test 2's assertion to the error the comment promises ( The comment states the point precisely — "findVitestBin surfaces the - expect(() => runControlMutant(dir, 'a.test.ts')).toThrow();
+ expect(() => runControlMutant(dir, 'a.test.ts')).toThrow(
+ /not defined by "exports"/,
+ );I applied this and it passes — the throw genuinely is that one. It also matches the sibling 2. With the resolver injected, - const worktree = mkdtempSync(join(tmpdir(), 'no-vitest-'));
+ // Never touched on disk — the injected resolver decides the outcome and
+ // the path only has to appear in the message.
+ const worktree = join(tmpdir(), 'no-vitest-unused');(Alternatively keep Note, not a defectAfter this change nothing verifies the link "a genuine Risk / security / performanceNo production behavior change, no new dependency, no I/O outside per-test temp dirs, and the planted shadow package lives inside a |
|
@qwen-code /takeover |
doudouOUC
left a comment
There was a problem hiding this comment.
LGTM. The default findVitestBin behavior remains unchanged, and the tests now exercise the intended error paths without relying on ambient TMPDIR node_modules layout.
|
🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 |
What this PR does
Stabilizes two environment-dependent tests in
packages/cli/src/commands/review/test-efficacy.test.tsthat fail on hosts where vitest resolves up-tree fromos.tmpdir(). Both tests keep every assertion verbatim; only the way the failure condition is produced becomes host-deterministic. ThefindVitestBinhelper gains an optional resolver parameter whose default is exactly the previous inline behavior, and one test plants a local shadow package instead of relying on a bare tmpdir having no vitest anywhere above it.Why it's needed
CI's ubuntu Test job fails with
AssertionError: expected [Function] to throw an errorin two cases:findVitestBin > names the search root when vitest cannot be resolvedandrunControlMutant > leaves the probe file byte-identical when it cannot run(PR run 30909672420; the same signature appears on the latest main run 30893612230). Both tests assumed nothing up-tree ofos.tmpdir()provides avitest/package.json— true on macOS dev machines, false on the project's self-hosted runner where anode_modulesabove TMPDIR supplies one. In that environment the first test never throws and the second actually executes the probe suite instead of throwing.Reviewer Test Plan
How to verify
mkdir -p /tmp/qwen-fake-tmp/node_modules && ln -s <repo>/node_modules/vitest /tmp/qwen-fake-tmp/node_modules/vitest, then runcd packages/cli && TMPDIR=/tmp/qwen-fake-tmp npx vitest run src/commands/review/test-efficacy.test.ts. With the old code both tests fail exactly as on CI; with this PR the full file passes (128/128).findVitestBinis called without the new parameter at its only production call site, so the default resolver (anchoredcreateRequire) is identical to before.toThrow(...)messages and the same byte-identical probe file restore.cd packages/cli && npm run typecheckplus ESLint/Prettier on the two touched files — all clean locally.Evidence (Before & After)
Before: both tests fail on the self-hosted ubuntu runner (and locally under the fake TMPDIR harness above). After: full file passes 128/128 in the repro environment and in 4 consecutive runs in the normal environment. Full evidence is in the e2e report comment below.
Tested on
Environment (optional)
macOS local runs plus a fake TMPDIR harness that simulates the Linux self-hosted runner's ambient vitest; the real ubuntu runner validates via this PR's own CI run.
Risk & Scope
findVitestBingains an optional parameter used only by tests; its default is the previous inlinecreateRequireanchor, so production behavior is unchanged.Linked Issues
None.
中文说明
本 PR 做了什么
稳定
packages/cli/src/commands/review/test-efficacy.test.ts中两个依赖环境的测试——它们在能从os.tmpdir()向上解析到 vitest 的主机上会失败。两个测试的断言全部逐字保留,只把失败条件的构造方式改为在任何宿主上都确定。findVitestBin增加一个可选解析器参数,其默认值与之前的内联行为完全一致;另一个测试改为种植本地 shadow 包,不再依赖裸 tmpdir 上方恰好没有 vitest。为什么需要
CI 的 ubuntu Test 任务以
AssertionError: expected [Function] to throw an error失败于两个用例:findVitestBin > names the search root when vitest cannot be resolved和runControlMutant > leaves the probe file byte-identical when it cannot run(PR run 30909672420;最新 main run 30893612230 同签名)。两个测试都假设os.tmpdir()向上没有任何vitest/package.json——在 macOS 开发机上成立,在项目自托管 runner 上不成立(TMPDIR 之上的 node_modules 提供了 vitest)。该环境下第一个测试从不抛错,第二个则真实执行了探针套件而非抛错。Reviewer Test Plan
如何验证
mkdir -p /tmp/qwen-fake-tmp/node_modules && ln -s <repo>/node_modules/vitest /tmp/qwen-fake-tmp/node_modules/vitest,然后cd packages/cli && TMPDIR=/tmp/qwen-fake-tmp npx vitest run src/commands/review/test-efficacy.test.ts。旧代码下两个测试与 CI 完全一致地失败;本 PR 下整文件通过(128/128)。findVitestBin在唯一生产调用点不传新参数,默认解析器(锚定 createRequire)与之前完全相同。toThrow(...)消息与相同的探针文件字节恢复。cd packages/cli && npm run typecheck加两个改动文件的 ESLint/Prettier——本地全部通过。Evidence (Before & After)
改动前:两个测试在自托管 ubuntu runner 上失败(本地用上述 fake TMPDIR 装置同样复现)。改动后:整文件在复现环境与常规环境 4 轮连续通过(128/128)。完整证据见下方 e2e report 评论。
Tested on
Environment (optional)
macOS 本地运行,外加模拟 Linux 自托管 runner 环境 vitest 的 fake TMPDIR 装置;真实 ubuntu runner 由本 PR 自身的 CI 运行验证。
Risk & Scope
findVitestBin新增仅测试使用的可选参数;默认值即原先内联的 createRequire 锚定,生产行为不变。Linked Issues
无。