测试金字塔
平衡测试套件:大量快单元测试,较少集成,极少端到端。
为什么
测试金字塔是按速度和信心分配测试精力的启发式。底——大量单元测试——秒级跑、抓大多回归、给精确失败位置。中——集成测试——分钟级跑、抓接缝 bug。顶——少量 E2E——数十分钟跑、抓断旅程变更但 flaky 且慢。倒金字塔团队(少单元多 E2E)终得 40 分钟 flaky 套件,难调试,没人本地跑。金字塔保持快反馈环快,把慢贵测试留给值得的少 数旅程。
何时使用
从项目开始就把金字塔当套件形状目标,周期性审计实际形状。若 E2E 套件增长快于单元套件,在反馈环退化前再平衡。
如何做
1. 测当前套件形状 - 按类型数测试: 单元、集成、E2E - 测每类型运行时间: 单元(<10s)、集成(<5min)、E2E(<20min) - 画金字塔: 若 e2e > integration > unit,你倒置了 2. 设目标比例(经典金字塔) - 单元: 70% 测试,<10s 总运行 - 集成: 20% 测试,<5min 总 - E2E: 10% 测试(3-15 条),<20min 总 - 按上下文调: UI 重应用可能 E2E 多,库几乎没有 3. 尽可能把测试下推 - 查表单验证的 E2E → 移到验证器的单元测试 - 查纯变换的集成 → 移到单元测试 - 测试越低反馈越快越精确 4. CI 中门控套件形状 - e2e 数超阈值(如 20)无审查即失败 - 变更文件单元覆盖低于 60% 警告 - 追踪套件运行时间作指标;每季涨 > 20% 即查 5. 每季重审再平衡 - 找可下推的测试(测逻辑非旅程的 E2E) - 删不守卫的测试(被测代码已删) - 保持快环快——这是金字塔的全部意义
示例
# 审计脚本: 按类型数测试并测运行时间 # scripts/audit-pyramid.sh echo "=== 测试金字塔审计 ===" echo "单元测试: $(find src -name '*.test.ts' | wc -l)" echo "集成测试: $(find tests/integration -name '*.test.ts' | wc -l)" echo "E2E 测试: $(find e2e -name '*.spec.ts' | wc -l)" echo "" echo "=== 运行时间 ===" time vitest run --reporter=dot 2>&1 | tail -1 # 单元 time vitest run --config vitest.integration.ts 2>&1 | tail -1 # 集成 time npx playwright test 2>&1 | tail -1 # E2E # 样本输出: # 单元测试: 342 # 集成测试: 48 # E2E 测试: 12 # 比例: 85% / 12% / 3%——健康金字塔,快反馈环完好。 # 倒金字塔(坏): # 单元测试: 18 # 集成测试: 24 # E2E 测试: 156 # 比例: 9% / 12% / 79%——40 分钟套件,没人本地跑,回归溜进。
常见问题
- ⚠倒金字塔(多 E2E 少单元)给 40 分钟 flaky 不精确套件——E2E 挂时根因可能在栈任何处,调试要数小时非数秒。
- ⚠"冰淇淋锥"(多手动、些 E2E、少单元)靠人抓回归,不扩展——团队长测试面长,手动覆盖必落后。
- ⚠把金字塔当刚性规则而非启发式导致把测试强塞错层——薄 UI 库可能合理地主要用 E2E/视觉测试,那没问题。
- ⚠只测测试数不测运行时间藏了真问题——100 条各 2 分钟的单元测试(因打数据库)比 20 条各 30 秒的 E2E 更糟。
最佳实践
- ✓同时追踪每层测试数和运行时间——金字塔关于快反馈,70/20/10 中 70% 跑 5 分钟不是健康金字塔。
- ✓每当测试慢或 flaky,问"能下推一层吗?"——大多测逻辑的 E2E 可成剥 UI 的同逻辑单元测试。
- ✓每季审计金字塔形状并设预算:如"单元套件须低于 10s,E2E 低于 20 条"——CI 中超限警告或失败。
- ✓按上下文调金字塔:后端微服务可能钻石形(多集成、些单元、少 E2E),对接缝重架构那是对的。