DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
晚安云;香港 CN2 ¥15/月
雨云;给项目一台云服务器

Vitest --changed 漏跑 setup 通过 require 加载的文件

setup 的 require 能读取新值,changed 筛选却可能漏跑测试。forceRerunTriggers 可让已知图外文件命中时运行完整集,但不会补全 require 依赖图。

修改了 setup 文件通过 require() 读取的辅助文件,完整测试会失败,vitest run --changed 却输出 No affected test files found 并成功退出。若 setup 自身修改能触发测试,只有它的 CommonJS 依赖变更被漏掉,应检查变化筛选的依赖图边界。

Vitest 5.0.4 有这条明确表现,正式 5.0.5 的相关解析仍以静态、动态 import 等已知依赖构建联系。CommonJS 的 require 调用不会因此自动进入同一张静态图;更新到 5.0.5 不能当作这类依赖已被完整追踪的保证。

setup 执行成功,不代表筛选器知道它读取了谁

例如 setup.cjs 中有 globalThis.value = require('./support/helper.cjs').value。完整运行时,Node 可以执行 require 并读到新值;但 --changed 在决定运行哪些测试时,没有这条从 helper.cjs 回到 setup 的依赖边,就可能提前得到空集合。

这是“文件仍存在,但读取关系没有进入筛选图”的情况。删除一个 import 目标后失去旧依赖联系,是另一条需要单独检查的路径;不要因为两者都显示空结果,就认为一个修正可以覆盖全部变更筛选问题。

先核对实际 Git 比较基准、测试 include、项目选择及 setup 配置。如果完整任务也没有收集到该测试,需先解决测试范围;只有完整运行能暴露 helper 变化造成的失败时,才符合这里的漏跑条件。

为图外辅助文件配置整组触发条件

已知一组文件会被 setup 通过 require 读取时,可以在 Vitest 配置的 test 层显式声明。下面是配置结构示例:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    setupFiles: ['./setup.cjs'],
    forceRerunTriggers: [
      '**/package.json',
      '**/vitest.config.*',
      '**/vite.config.*',
      '**/support/**/*.cjs',
    ],
  },
});

support 路径是示例,要改成实际辅助文件范围。这里保留了工具默认的三个触发模式,避免用新数组替换默认值时漏掉原有配置变化。与 --changed 配合时,Git diff 中命中这些 glob 的文件会触发完整测试集;它不会修好 require 的依赖图,也不会只推导出依赖该文件的少数测试。

配置应放在实际运行采用的 Vitest 入口。多项目配置要按项目继承关系核对,不要只修改一个未被加载的配置文件。辅助文件还不能被服务端 watch 忽略规则排除;需要 watch 重跑时,另验它确实能收到该文件变化。

如果 require 会动态拼出任意路径,窄模式无法可靠覆盖,就让关键合并任务使用原有完整测试入口。保留环境变量、项目与隔离设置,并评估完整运行的资源开销。增加 --passWithNoTests 无法修复漏跑,因为错误本来就以成功退出表现出来。

验收先修改一个已匹配的辅助文件,使现有断言明确失败,确认 --changed 真正运行测试并失败;再恢复正确值,确认恢复通过。另选一个不在模式内的文件检查边界,避免把“加了配置”误当成所有图外依赖都已覆盖。