别在每次提交时运行整个测试套件 🚫🧪
Source: Dev.to

问题
在每次提交前运行整个测试套件会导致:
- ⏰ 慢 – 浪费宝贵的开发时间
- 😤 令人沮丧 – 打断你的工作流状态
- 🔄 冗余 – 测试你根本没有改动的代码
大多数开发者:
- 完全跳过测试(危险!)
- 等待冗长的测试运行(令人沮丧!)
- 推送代码并祈祷 CI 能捕捉到问题(风险极大!)
必须有更好的办法。
解决方案:test‑staged
test-staged 就像 lint-staged,但用于测试。它能够智能地识别与您在 stage 中的更改相关的测试,并仅运行 这些。
有多智能?
test-staged 根据您使用的测试运行器采用 不同的策略:
| 运行器 | 策略 |
|---|---|
| Jest / Vitest | 使用原生依赖图分析 (--findRelatedTests / vitest related) |
| Mocha / Ava | 将源文件映射到测试文件(例如:user.ts → user.test.ts,src/api/users.ts → src/api/__tests__/users.test.ts) |
30 秒快速入门
安装非常简单:
npm install -D test-staged
# ou
pnpm add -D test-staged
# ou
yarn add -D test-staged
# ou
bun add -D test-staged
真的。 默认零配置。
配置为 Pre‑Commit Hook
当你与 Husky 结合时,魔法就会发生:
# Instale o husky
npm install -D husky
npx husky init
# Adicione test-staged ao pre‑commit
echo "npx test-staged" > .husky/pre-commit
现在,每次提交时,hook:
- ✅ 只运行与更改相关的测试
- ⚡ 在几秒钟内完成,而不是几分钟
- 🛡️ 如果测试失败,阻止提交
真实案例
示例 1 – 单文件更改
你正在开发用户认证功能:
# 你修改了:
git add src/auth/login.ts
test-staged 仅执行:
src/auth/__tests__/login.test.ts
src/integration/__tests__/auth-flow.test.ts # (因为导入了 login.ts)
且 不执行:
src/payments/__tests__/*.test.ts ❌
src/dashboard/__tests__/*.test.ts ❌
# (超过 200 条不相关的测试)❌
结果: 测试在约 3 秒内完成,而不是约 2 分钟。
示例 2 – 重构工具函数
你重构了一个工具函数:
# 你修改了:
git add src/utils/formatDate.ts
test-staged 找到 所有 依赖它的测试:
src/utils/__tests__/formatDate.test.ts
src/components/__tests__/DatePicker.test.ts
src/pages/__tests__/Dashboard.test.ts
足够智能以捕获间接依赖,足够快速以保持生产力。
示例 3 – Monorepo 支持
在使用 monorepo 吗?test-staged 为你覆盖:
# 你在 packages/ui 目录下
git add Button.tsx
仅执行:
packages/ui/__tests__/Button.test.tsx
且 不执行以下目录的测试:
packages/api/ ❌
packages/cli/ ❌
为什么你会爱上它
🎯 零配置
自动检测:
- 您的包管理器 (npm, pnpm, yarn, bun)
- 您的测试运行器 (Jest, Vitest, Mocha, Ava)
- 您的项目结构 (monorepo 或单包)
⚡ 极其快速
在一个典型的包含 500+ 测试的项目中:
| 之前 | 之后 |
|---|---|
| 每次提交 2‑3 分钟 | 每次提交 2‑5 秒 |
实际使用提升约 36 倍
🧠 真正智能
Jest / Vitest – 使用原生依赖图:
// 如果你修改 userService.ts
// 它会找到引用它的测试:
import { createUser } from './userService';
import { validateUser } from './userService';
Mocha / Ava – 使用模式匹配:
src/models/user.ts → src/models/user.test.ts
src/api/users.ts → src/api/__tests__/users.test.ts
lib/parser.ts → lib/parser.spec.ts
🛠️ 需要时可自定义
虽然无需配置即可使用,但你可以自定义它:
通过 package.json
{
"test-staged": {
"runner": "jest",
"mode": "related",
"testExtensions": [".test", ".spec", ".e2e"]
}
}
通过 .test-stagedrc.json
{
"runner": "vitest",
"testExtensions": [".test", ".spec", "Test", "E2E"]
}
支持的测试运行器
| 运行器 | 检测方式 |
|---|---|
| Vitest ⭐ | 原生 vitest related(依赖图) |
| Jest | --findRelatedTests |
| Mocha | 文件模式映射 |
| Ava | 文件模式映射 |
⭐ 原生 --findRelatedTests(依赖图)
Mocha ✅ 文件模式匹配
Ava ✅ 文件模式匹配
更多运行器即将推出!
开发者体验
看看你的工作流程是怎样的:
# 做出你的修改
vim src/components/Button.tsx
# 添加到暂存区
git add src/components/Button.tsx
# 提交(test‑staged 会通过 pre‑commit hook 自动运行)
git commit -m "fix: 按钮的 hover 状态"
# 输出:
Running tests for staged files...
✓ src/components/__tests__/Button.test.tsx (2 tests) 0.8s
Tests passed! ✨
[main abc1234] fix: 按钮的 hover 状态
无需手动运行测试命令。无需等待。提交不会出现破损。
常见问题
问: 如果我想运行所有测试怎么办?
答: 只需跳过钩子:git commit --no-verify,或手动运行你的测试套件。
问: 它能在 CI 中使用吗?
答: 能!你的 CI 仍然应该运行完整的测试套件。test‑staged 旨在提升本地开发的速度。
问: 集成测试/E2E 测试怎么办?
答: 如果它们导入了你修改的文件,test‑staged 会找到它们。你也可以自定义要运行的测试。
问: 可以不使用 Git 钩子吗?
答: 当然可以!只需在需要时手动执行 npx test-staged。
立即尝试
在不到一分钟的时间开始:
npm install -D test-staged husky
npx husky init
echo "npx test-staged" > .husky/pre-commit
然后进行一次提交,看看魔法如何发生。 ✨
链接
总结
如果你仍然在每次提交时运行完整的测试套件,那是在浪费时间。test-staged 为你提供:
- ⚡ 更快的提交 – 只需几秒而不是几分钟
- 🎯 更好的聚焦 – 只测试已更改的内容
- 🛡️ 更安全的代码 – 测试真正执行,而不是被跳过
- 🚀 更佳的开发者体验(DX) – 零配置,直接可用
试试看并告诉我你的感受!未来的你会感谢你的。🙌
你已经尝试过 test-staged 吗?你当前的 pre‑commit 测试策略是什么?在下方评论分享吧!👇
