---
name: test-strategy
description: 用于制定或调整测试策略、选择测试范围与命令、决定是否跑全量/场景/性能测试；普通编码沿用项目既有测试命令，不自动改写测试结构。
---

# 测试策略

## 术语

- **功能基线（baseline）**：使用 test double 隔离外部依赖、纯代码、按模块运行、全项目 ≤5 分钟。用户口语中的“基准测试”默认指它。
- **场景测试（scenario）**：真实依赖和业务流程，按 flow 按需运行。
- **性能测试（performance）**：微基准、负载、压力、浸泡，有 SLO 或 profile 证据才运行。

不替代 `deep-dive-review` 的独立审查流程。

## 默认规则

1. 项目 `AGENTS.md`、`TESTING.md` 或 CI 中的测试命令、范围与门禁优先；用户显式要求覆盖项目默认；本 skill 只在项目未规定时提供默认。
2. 功能基线默认只跑受影响模块。全量功能基线只允许：用户明确要求、发布门禁、定时 CI、项目显式策略。
3. 场景测试按 flow 选择，默认不收集、不加载场景测试模块；发布前全量场景需要用户明确要求或项目预先声明。
4. 性能测试必须有 SLO/性能目标，或 profile/复杂度证据；宽泛关键词不构成理由。
5. 影响面不明时跑最近模块并报告未覆盖风险；仍不确定时询问用户，不默认全量。

## 三轨道

| | 功能基线（baseline） | 场景测试（scenario） | 性能测试（performance） |
| --- | --- | --- | --- |
| 测什么 | 纯代码逻辑、分支、边界、参数 | 真实业务流程与依赖 | 微基准/负载/压力/浸泡 |
| 依赖 | test double | 真实依赖 | 真实依赖或固定基准环境 |
| 速度 | 全项目 ≤5 分钟 | 按 flow 计 | 按目标计 |
| 默认 | 受影响模块 | 不收集、不加载测试模块 | 不运行 |
| 位置 | `tests/baseline/` 或标记 `baseline` | `tests/scenario/` 或标记 `scenario` | `tests/performance/` 或独立 bench |

三条轨道使用不同目录或 runner 标记，禁止混跑。

## 决策流程

1. 读项目测试策略与现有命令；项目没有 runner、测试目录或映射表时，按“首次接入”处理（见 `references/selection-and-commands.md`），先征得用户同意再改依赖或目录。
2. 列出改动文件、公开契约变化和风险。
3. 映射到模块；没有映射表时按 reference 建立最小映射，命令从项目脚本或 CI 核实。
4. 跑受影响模块的功能基线；为改动分支补用例；公开契约变更追加直接消费者的契约测试，最多再取一跳传递消费者。
5. 验收需要真实调用时匹配 flow；有 SLO/profile 证据时跑性能测试；全量按默认规则 2；影响不明按默认规则 5。

## 功能基线

- 外部依赖用 test double；文件系统默认内存 fake。只有文件格式、路径或权限语义本身是契约时，才允许隔离临时目录：独立根目录、结束清理、不读写用户目录或共享状态，单例 ≤200ms。
- 覆盖改动涉及的分支：正常、边界、空值、非法输入、错误、状态转换、参数组合；确定性；只断言可观察行为。
- 单个用例默认目标 200ms。纯代码但超标的用例进 `slow-baseline` 标记，按模块按需运行，记录原因、预算和 owner，不计入 5 分钟默认；不能用它隐藏真实 I/O。
- 全量测量口径：依赖已安装、默认 worker、命令启动到退出、包含收集和 fixture、不含依赖安装；记录机器/commit/workers，取 3 次中位数。细则见 `references/baseline-tests.md`。
- 用户明确要求的一次性全量按用户范围执行并标注为一次性验证，不改变 baseline 的 5 分钟达标状态。
- 契约测试的定义、消费者定位和放置位置见 `references/baseline-tests.md`。

## 场景测试

- 按 flow 目录维护；默认命令在加载测试模块前排除场景测试，验证收集到 0 个场景且未加载场景测试模块。运行时跳过不能证明隔离。
- 独立环境、账号和数据；自建自清、唯一命名空间；不得连接生产或共享开发数据。
- flaky 用例隔离并记录原因，不用盲目重试；全量场景只在发布前且用户或项目明确要求时运行。
- flow 目录、默认排除配置和清理规则见 `references/scenario-tests.md`。

## 性能测试

- 触发前提：项目有 SLO/性能目标，或 profile/复杂度分析证明改动影响热点；仅“缓存、序列化、启动”等关键词不构成理由。
- 微基准、负载、压力、浸泡分开；报告 p50/p95/p99、吞吐、错误率、CPU/内存/GC，不只报平均值。
- 重复性测量要求同 commit、同环境、同数据、同构建；A/B 对比允许对照/候选两个 commit，但必须同机器、同数据、同 release 构建，交替或随机顺序运行，用置信区间或约定容差判断。
- 只有稳定、专用 runner 才允许硬失败；共享 runner 只记录趋势和告警，不阻塞 PR。
- 子类型、数据生命周期、CI 分层和工具见 `references/performance-tests.md`。

## 证据

每个命令一个块：

```
命令：
退出码：
结果：pass / fail / skip（数量）
耗时：
环境：机器/runner、commit、workers
未运行：场景 / 性能 / 全量及原因
```

修 bug 时记录“修复前红灯输出 → 修复 → 修复后绿灯输出”；无法复现时写明原因和替代证据。“测试通过”没有命令和输出不算证据。
应有测试的范围若收集到 0 个测试或全部跳过，报告该范围未验证；仅证明场景被排除不等于功能基线通过。

## 反模式

- 小改动直接跑全量测试，或把只跑子集当作全量达标。
- 为单元逻辑写端到端测试，或在多层重复同一断言。
- mock 掉被测对象本身，或 mock 过度导致测试只验证 mock。
- 用 sleep、固定端口、共享数据库、真实网络制造不确定性。
- 追求 100% 覆盖率而测试无风险代码。
- 场景测试默认执行，或把不稳定场景塞进功能基线。
- 用重试掩盖 flaky，而不是定位原因。
- 用单次跑分或平均值下性能结论，或在共享 runner 上把噪声当回归。
- 对没有 SLO 或热点证据的改动跑性能测试。

## 参考资料

- `references/baseline-tests.md`：覆盖矩阵、test double、契约测试、时长与基线债务。
- `references/scenario-tests.md`：flow 目录、默认排除、环境/数据/清理与 flaky。
- `references/selection-and-commands.md`：优先级、模块映射、首次接入与常见生态命令。
- `references/performance-tests.md`：微基准、负载/压力/浸泡、A/B、门禁与工具。
