测试规范
1. 测试框架
- 单元/集成测试: Vitest(与 Vite 生态无缝集成)
- E2E: Playwright(平台阶段启用)
2. 测试设计原则
- 目标驱动: 测试先回答"本次要证明或否证什么风险",禁止为了凑覆盖率、补截图或制造形式上的安全感而写低价值用例。
- 失败路径优先: 修复 Bug、补守卫或收紧契约时,优先补会在缺陷存在时失败的断言,再补成功路径回归,而不是只测当前实现已经能通过的分支。
- 最小充分验证: 优先运行与改动直接相关、最能区分风险的定向用例;只有当风险外溢到跨模块链路时,才升级为更大范围测试。
- 单用例单风险: 每个测试块应尽量围绕一个行为风险、边界条件或回退契约命名,避免把多个不相关断言堆在同一用例里导致失败归因模糊。
3. 测试组织
- 单元测试: 与源文件同目录,命名
*.test.ts- 例:
packages/core/src/utils/index.test.ts
- 例:
- 集成测试:
tests/目录,命名*.test.ts - E2E:
tests/e2e/目录,命名*.e2e.test.ts
4. 测试策略
4.1 按风险分级执行
| 级别 | 适用场景 | 命令 |
|---|---|---|
| 定向测试 | 日常开发、单文件改动 | npx vitest run <file> |
| 全量测试 | 提交前、跨模块改动、发布前 | pnpm test / pnpm -r test |
| Review Gate | 阶段归档前、关键交付 | pnpm test + typecheck + lint |
原则: 不是所有场景都一刀切全量执行。按改动类型选择:
- 纯工具函数 → 定向测试
- 跨模块 API 变更 → 全量测试
- 阶段收口 → 全量 + coverage
4.2 测试优先策略
- 优先补当前缺陷会打断的断言、失败路径与边界行为
- 不把测试阶段退化为机械补 coverage
- 有效断言 > 覆盖率数字
4.3 命令预算与升级条件
| 命令类别 | 典型命令 | 默认 timeout | 适用场景 | 升级条件 |
|---|---|---|---|---|
| 定向测试 | npx vitest run path/to/file.test.ts | 10 分钟 | 单模块逻辑、小范围修复 | 发现跨模块回归或接口契约变化时升级到全量测试 |
| 全量测试 | pnpm test | 30 分钟 | 大规模重构、关键逻辑变更、周期性回归 | 核心链路或发布前收口时升级到 pnpm verify |
| Coverage | pnpm test:coverage | 30 分钟 | 覆盖率治理、回归任务、核心模块补测 | 若覆盖率下滑或存在核心链路改动,应补充定向/全量测试结果一起提交 |
| Verify | pnpm verify | 60 分钟 | 发布前、跨模块流程、需要完整证据链 | 仅在需要串联 lint + typecheck + test 时使用,不作为普通小改动默认命令 |
5. 覆盖率目标
| 范围 | 目标 |
|---|---|
| 整体 | >= 60% |
packages/core/ | >= 80% |
packages/cli/ | >= 60% |
提升策略:先补缺口分析,再逐模块推进,不追求一次性全量达标。
5.1 覆盖率冲刺执行方法
- 开始补测试前,必须先做一次 fresh 基线分析:以当前
pnpm test:coverage输出为准。 - 在编辑测试前,必须先估算"离目标还差多少覆盖行数",记录当前 lines、目标 lines、粗略缺口和预期先打的高 ROI 切片。
- 估算缺口后,优先选择高 ROI 切片:大体量低覆盖文件、已有测试基础的模块、能稳定命中失败路径的 service。
- 覆盖率补测坚持"小步快跑":每次只改当前切片的测试文件,改完立即运行该测试文件或同级最小定向命令,先证明当前新增断言能稳定通过,再继续下一个切片。
- 全量
pnpm test:coverage只在两种情况下执行:一是累计的预期增益已经接近阶段目标,二是需要刷新全仓基线并决定下一批 ROI;禁止每补完一个小文件就立刻重跑全量 coverage。 - 覆盖率冲刺过程中,必须持续把基线、估算缺口、已补切片、最近一次全量 checkpoint、剩余高 ROI 候选与未覆盖边界写入
docs/plan/todo.md或专项记录,避免方法、进度和证据只停留在对话里。
6. 测试原则
- 行为导向: 测试聚焦业务行为,验证"做了什么",不是复刻实现细节。
- 最小复现优先: 根因不明确时先编最小复现测试,一次验证一个假设。
- 覆盖维度: 至少覆盖主流程、失败路径、边界条件。
- Mock 原则: mock 不掩盖真正的集成风险。优先真实调用,mock 仅在外部依赖不可控时使用。
- 失败处理: 测试失败时先解释根因,再决定改代码还是改测试。严禁直接改断言让它绿掉。
- CI 最终裁决: 修复的验收标准是 CI 全部通过,不是本地通过。
7. 测试代码质量
- 测试代码本身也需要通过 lint + typecheck
- 测试描述(
it('does X'))聚焦业务行为,使用清晰语言 - 避免过度耦合内部实现细节
8. 高效运行技巧
8.1 按需定向测试
在日常开发和修复 Bug 过程中,优先仅运行与本次改动直接相关的测试文件。全量测试极其缓慢,频繁运行会严重阻塞开发流程。
- 优先选择能直接命中当前风险、失败路径或契约边界的测试
- 若关键字方式无法稳定命中同类
*.test.ts,优先使用npx vitest run path/to/file.test.ts
8.2 排查慢速测试
若发现测试异常缓慢,检查是否在每个 test 中重复进行了昂贵的资源创建/销毁操作,应尽量利用 beforeAll 和 afterAll。
9. 样例数据与夹具
- 准备 Dependabot 告警样例数据
- 准备 lockfile 漂移失败样例
- 准备 Code Scanning 样例数据
- 关键流程可在不依赖线上真实仓库的情况下做回归测试
10. 相关文档
本文档在 1.0.0 前参考 momei 项目的成熟做法完成继承与适配;1.0.0 后按项目自身实践持续演进,形成自有规范。