返回博客

Turborepo 全量测试红了,但锅不是你的

在一个 pnpm + Turborepo monorepo 里,我只新增了一个 UI 组件,本地 vitest run 12 个用例全绿,typecheck 干净,scoped build 也没问题。然后提交前跑 pnpm test(即 turbo run test 全量门禁),结果冒出来 2 个失败文件,而且看文件名——我根本没碰过那两个目录。

第一反应:完了,我动了什么底层依赖把别人的测试搞坏了?

现象

Test Files  2 failed | 12 passed

失败的是 accordion/accordion.test.tsx_probe_overlay.test.tsx。我新增的是 alert/ 目录,和这两个文件毫无交集。

更诡异的是,我之前跑过一次"基线记录",turbo 输出了 >>> FULL TURBO ... cache hit, replaying logs,全部绿色,11 个测试文件全过。现在却变成了 14 个文件、2 个失败——多出来 3 个文件从哪来的?

根因

问题一:untracked WIP 文件

git status 一跑就露馅了:

?? packages/ui/src/accordion/
?? packages/ui/src/slider/
?? packages/ui/src/_probe_overlay.test.tsx

这三个目录/文件都是 ??——完全未追踪,不是我的工作,是另一个并行会话(或另一个 agent)在做别的功能,半成品搁在工作区里还没提交。它们的测试写了断言但实现还没跑通,所以一旦 vitest 扫到,就爆红。

问题二:turbo 缓存命中掩盖了真实状态

┌─────────────────────────────────────────────────┐
│  基线时(untracked 文件还不存在)                 │
│  cache key = git HEAD SHA → 命中缓存 → 回放旧日志│
│  结果:11 文件全绿 ✅(但是假象)                │
└─────────────────────────────────────────────────┘

turbo 的缓存键基于 git 追踪文件的哈希,untracked 文件不影响缓存键。并行会话在我开始之后写入了 untracked 文件,下一次有代码变更(我新增 alert 组件)导致缓存失效,turbo 重新执行,这才把那 3 个 untracked WIP 文件一起扫进去了——14 个文件,2 个失败。

坑:turbo cache hit 的绿色基线可能是谎言

当工作区存在 untracked 文件时,turbo run test 的缓存命中只能代表缓存写入时刻的状态,不代表当前工作区的真实状态。如果并行会话在缓存写入之后又丢进来新文件,基线就已经过期了,但 turbo 仍然会骄傲地打印"cache hit, replaying logs"并回放绿色日志。

正解

第一步:先 git status,不要急着"修"

git status --short

找出 ?? 行。把失败的测试文件集合和 ?? 集合对比——如果失败文件全在 untracked 集合里,那这些红不是你的。

第二步:独立验证自己的 scope

# 只跑自己的包
pnpm --filter @ui/components exec vitest run alert
# typecheck
pnpm typecheck
# scoped build
pnpm build --filter=www

三项全绿,自己的工作就干净。

第三步:需要看真实全量状态时用 --force

turbo run test --force

绕过缓存,强制重新执行,看到的才是现在工作区的真实情况。

第四步:不要删、不要改别人的 untracked 文件

这是别人的在途工作。你要做的是:提交自己的改动,然后在报告里写清楚——

我的 scope(alert 组件)12 个测试全绿,typecheck 和 build 均干净。全量 pnpm test 门禁红了,是 accordion/_probe_overlay.test.tsx 这两个 untracked WIP 文件导致的,我未动过它们,请相关同学跟进。

正解:区分 scope,用 --force 看真相,surfacing 而不是 fixing
  1. git status --short 识别 ?? 文件集合
  2. 对比失败文件是否全在 untracked 集合里
  3. 独立用 --filter=<pkg> 跑自己的测试验绿
  4. 怀疑缓存基线失真时加 --force 强制重跑
  5. 汇报污染情况而不是替别人"修"

一句话外卖

在多并行会话的 monorepo 里,turbo run test 红了先 git status 看 untracked 文件,turbo 的缓存命中基线随时可能因为 untracked WIP 而失效——先验证自己的 scope 干净,再 surface 污染,不要帮别人修半成品测试。