# Test Module Rules

## 范围与目标
适用于 `tests/`。测试用于验证真实行为、稳定契约、模块协作和完整流程，而非提高覆盖率数字。禁止为通过测试或提高覆盖率制造无意义断言。

## 层级与选择
- `tests/client/`、`tests/host/`：单元测试。覆盖纯函数、数据转换、Schema、状态转换、Tool 参数、权限、Runtime/Client 局部逻辑。
- `tests/integration/`：集成测试。验证 Host/Runtime、Orchestrator/Storage、Tool/Capability、Workflow/Runtime、持久化等多模块协作。可用受控基础设施，但不得全量 Mock 内部模块。
- `tests/contract/`：包与构建契约门禁。验证发布包形态（exports/files/dsh 元数据）、挂载契约（patch 文件）、构建产物与随包资产。只做静态文本/产物断言，不验证运行时协作。
- `tests/e2e/`：端到端测试。覆盖完整 Workflow、Client → Host → Runtime、用户关键路径。不得替代 Unit / Integration。

选择能最低成本验证目标行为的最低测试层级。不得因 E2E 可测而跳过 Unit / Integration，也不得为数量把真实协作全部 Mock 成 Unit。

## 文件与命名
- `tests/client/`、`tests/host/` 必须镜像对应 `src/` 目录。
- `tests/contract/` 不镜像 `src/`：其断言对象是包级产物与构建链路，按被验证的契约命名。
- 测试文件统一为 `<source-name>.test.ts`。源码移动或重命名时，同步调整测试位置与 import。
- 测试名格式：`test_<行为>_<条件>_<预期>`，描述行为而非实现。
- 纯类型、声明、barrel、常量、极薄适配层、已被上层测试覆盖的代码，不强制创建空测试文件。
- 任何新增可测试业务逻辑必须有相应测试覆盖。

## 编写规则
- 使用 AAA：Arrange / Act / Assert。一个测试聚焦一个行为，多行为应拆分。
- 测试必须独立：不得依赖执行顺序、其他测试数据、共享可变状态、残留文件、数据库、全局变量或 Mock 状态。
- 时间、随机数、异步必须确定：使用 fake timer、固定时间、固定随机源、可控 Promise。显式等待目标完成，禁止任意 `sleep`。
- 测试数据最小、可读、与目的直接相关。复杂对象用 Factory / Fixture。不得修改全局 Fixture 影响其他测试。
- 断言必须验证可观察结果与业务语义。避免 `toBeDefined`、`toBeTruthy` 等空断言。避免测试私有变量、内部临时函数、无关调用顺序。
- 必测正常路径、失败路径、边界条件。错误测试需验证实际错误语义，而非仅“抛出异常”。
- Mock 只用于隔离测试边界。禁止 Mock 被测对象、所有内部函数或 Mock 到无法验证真实行为。需要大量 Mock 时，检查测试层级、模块耦合与边界。
- 测试代码本身需维护：命名清晰、单一职责、避免重复、隐藏状态、过度抽象。

## 新增、修改与重构
- 新增业务逻辑时，必须同时新增或修改测试。无法合理 Unit Test 时，判断是否应使用 Integration / E2E 或调整模块边界。
- 修改测试前确认：保护的行为是什么、失败来自代码/测试/环境、是否存在真实行为变化、是否降低验证强度、是否应新增测试。
- 禁止仅为让 `pnpm test` 通过而删除有效断言或放宽条件。
- 行为不变重构：测试应首先验证行为未变。失败先查 import / path / dependency / 环境；若实际行为变化，停止并报告。
- 行为变化必须说明：旧行为 → 新行为 → 为什么改变 → 哪些测试受影响。
- 测试失败时不要立即修改测试。先定位是实现、测试还是环境问题；无法确定原因时，不得改断言消除失败。

## 覆盖率
新增业务代码行覆盖率目标：≥ 80%。覆盖率用于发现未覆盖代码，不是唯一质量指标。禁止刷覆盖率、无意义测试、无意义断言、执行代码但不验证结果、Mock 掉关键行为、删除有意义测试。未达标需说明原因。

## 核心原则
行为优先于实现；契约优先于覆盖率；独立性优先于测试数量；合适层级优先于测试数量；真实协作优先于过度 Mock。

测试必须回答：这段代码应该做什么？现在是否仍然这样做？失败时哪里发生了变化？