目标
只会在固定顺序下通过的套件,本质是测试之间在 invisibly 共享状态。带种子的乱序执行把“运气好”变成可测试的属性:要么所有顺序都通过,要么某个具体的泄漏有名字、有生产者、有修复。配合消费者开头的“世界必须为空”前置断言,泄漏定位比任何调试器都直接。
步骤要点
- 先把两个文件正反两种顺序各跑一遍,一过一挂即证明状态经由共享资源从一个文件泄进另一个。
- 用多个种子的全量乱序运行度量影响面,统计各种子的失败数,零失败的种子就是一直掩盖泄漏的幸运顺序。
- 用失败种子加文件过滤定位到具体测试,它在该顺序下的前驱就是泄漏生产者,两者都有名有姓。
- 给消费者加“世界为空”前置断言:乱序下失败、单独跑通过,把神秘的他者失败变成精确的泄漏探测器。
- 在生产者侧补真正的 teardown 或改用每测试独立夹具,随后用失败种子复跑加无种子乱序双验证顺序无关性。
排错提示
每个种子失败点都不一样说明存在多个独立泄漏,从前置断言失败的消费者开始逐个修,每修一个失败面就缩小一圈;全量乱序太慢就改成每晚或每个 PR 跑一次,配合文件级并行把墙钟时间拉平;泄漏源在测试文件之外的单例(模块级缓存、连接池)时,暴露 reset 钩子挂在全局 setup,或按 worker 重新实例化。
适用边界
乱序只证明观测到的顺序下的隔离,罕见交错还需显式并发测试或压力循环;种子含义随 runner 版本变化,登记顺序类 bug 时连同 runner 版本一起记录。
代码示例
# Reverse the usual order -- does it still pass?
npx vitest run tests/auth.test.ts tests/orders.test.ts
# FAILS: orders lists 3 rows, expected 1
# Reproduce with a recorded seed
npx vitest run --sequence.shuffle --sequence.seed=22
# × orders > lists orders for the current tenant
# After fixing the producer teardown
npx vitest run --sequence.shuffle --sequence.seed=22 # all pass
npx vitest run --sequence.shuffle # all pass, any order