eo-test · diff

git:20260724.2f43c94 to git:20260724.5da3e6a

1 added, 1 removed. Audit A to A.

---
name: eo-test
description: |
为某个 change 编写并执行测试(以其验收清单为锚),产出 test.md 报告。严禁修改业务代码。触发:给这个 change 写测试 / 出测试报告 / test.md / /eo-test。
NOT FOR: 与 change 无关的日常跑测试或补单测(直接做即可,不产报告)。
---
# eo-test — 测试
以 change 的验收清单为锚编写并执行测试,产出结构化测试报告。核心目标是**验证**而非**修复**。
## 职能边界
1. **绝对禁令**:**禁止修改任何非测试相关的业务源码**。发现 bug 只记录并建议修复,不自行改源码。
2. **操作范围**:仅允许修改、新增测试文件与测试目录内容。
3. **输出目标**:测试代码 + `test.md` 报告 + 对话速报。
## 核心原则
1. **以 AC 为锚**:change.md §2 验收清单逐条推导——每条 AC 至少一份**验证证据**(不必是本 skill 新写的测试:implement 已留下且审计通过的测试、一次性执行记录都算数);§3 各 TODO 的完成判据(如有)作为补充覆盖点。AC 规范见 [../eo-shared/ac-spec.md](../eo-shared/ac-spec.md)
2. **审计 + 补缺,不重写**:implement 落下的测试是本 skill 的**输入**而非空白——先盘点已有覆盖并审计其真实性,只为缺口编写。独立性来自**独立审计与独立执行**,不来自重新编写
3. **AC 决定验什么,代码决定拿什么验**:AC 是**断言**的来源,不是**输入**的唯一来源。只按 AC 文字正向推导,验的永远只是「AC 想到的路径」——AC 写的是用户视角的期望行为,不会写出 `""` / `null` / 越界值 / 并发时序这类输入,它们只存在于实现的分支、默认值与空值处理里。**再多跑几遍环境矩阵也发现不了 AC 没想到的输入**
4. **回归资产分层**:永久测试文件只给逻辑密集、边界多、会被后续变更反复触碰的验证点;其余验证点以一次性执行证据(命令 + 关键输出记入 test.md)作证——测试深度随风险浮动,与 AC 的「条数不模板化」(ac-spec)同一原则
5. **重验证的唯一执行者**:auto-heavy AC(起服务 / 多环境组合 / 点击流)由本 skill 跑并勾选,implement 不跑——环境矩阵在这里一次跑完,不在三个阶段各重演一遍
6. **验证驱动**:所有职能围绕「证明代码是否符合 AC」展开
7. **独立报告**:固定产出到 `eo-doc/changes/<change-id>/test.md`
## 前置条件
- **必须能找到 `.eo-project.json`**。同目录存在 `.eo-project.local.json` 时顶层字段覆盖合并(local 优先)。找不到 → 报错退出,提示运行 `/eo-project-init`
- `eo-doc/changes/<change-id>/change.md` 已存在,且相关代码已实现(status: implementing 或 reviewed)
- `tier: light` 的 change 默认不经本 skill(重验证出现即扩档,见 eo-implement 轻模式)。用户显式要求时以 §2 AC 为锚执行,但为**只读语义**:测试代码照常落库,结论走对话速报,**不写 test.md 进 change 目录、不动 AC 勾选、不改 status**;发现缺陷 → 已 archived 的走 /eo-fix
## 工作流程
### 阶段一:单元测试(审计 + 补缺)
1. **消费 lessons**:按 [../eo-shared/lessons.md](../eo-shared/lessons.md) §1 扫 INDEX 匹配 trigger,命中读「规则」节带入——**尤其是环境相关的项目 lesson**(起停命令、单次代价、环境由谁起属项目特异知识,只可能在项目 lesson 里,不在本 skill)
2. **盘点已有覆盖并审计**:读本次 diff(frontmatter `base_commit` 起算,或 `[<change-id>]` 前缀的提交,**含 implement 落下的测试文件**),建立「AC → 已有测试」映射;逐条审计已有测试的真实性——断言是否真实覆盖对应 AC、有无被弱化/删除、有无过拟合/硬编码特判。审计通过的**不重写**;测试代码问题由本 skill 直接修正
3. **提取缺口验证点**:读 change.md §2(AC 逐条)与 §3(TODO 完成判据,如有),对照步骤 2 的映射列出**无覆盖**的验证点清单;逐条标注 **light / heavy**(heavy = 起服务 / 多环境组合 / 点击流)与适合单测 / 需集成验证
4. **读实现取输入**:从步骤 2 已读的 diff 中,从**分支、默认值、空值与边界处理、类型转换**提取 AC 没写、已有测试也没碰、但代码实际会遇到的输入,补进缺口清单——AC 给断言,代码给输入(核心原则 3)
5. **补缺编写**:只为缺口写测试,遵循项目既有测试目录与命名约定;按**回归资产分层**(核心原则 4)取证据形态——逻辑密集 / 边界多 / 共享路径的落成测试文件,其余以一次性执行证据作证(命令 + 关键输出记入 test.md「一次性执行证据」节,不落测试文件)
6. **执行**:全量运行(implement 已写 + 本 skill 补写)收集结果
7. **失败分析**:测试代码自身写错 → 直接修正测试;业务代码 bug → **停手**,记录到报告并建议走 /eo-implement 修复循环
### 阶段二:集成 / 场景验证(重验证,一次跑完)
对 **auto-heavy AC** 与其余不适合单测的 AC(用户视角操作链、端到端行为),按其验证口径(「验证」栏,省略时按声明本身)描述的操作编写独立验证流程;捕获命令输出、退出码、运行结果作为执行证据。
**环境纪律**(详见 [../eo-shared/ac-spec.md](../eo-shared/ac-spec.md)「重验证的环境纪律」):环境**假定已就绪**——先探测复用、**不主动停**,只在需要换环境组合时重启;**按环境组合分组跑**,一次起环境跑完该组合下的全部验证点,不为单条 AC 反复起停。
验证通过 → **勾选对应 auto-heavy AC**(本 skill 独有的勾选权);light 项 implement 已勾不重跑,manual 项不碰。
### 阶段三:报告与速报(轮次留痕,追加不覆盖)
1. 按 [references/test-template.md](references/test-template.md) 维护 `eo-doc/changes/<change-id>/test.md`:
- **首轮**(文件不存在):全量写入,失败项同步建入 FAIL 台账(FAIL-x 编号跨轮稳定;根因区分 `implementation` / `test-harness`——测试代码错误由本 skill 修正后直接核销,不留给修复循环)
- **复审轮**:**不重写报告**——先核销台账(`fixed` 项复测:过 → `verified`,仍失败 → 回 `open` 一句话说明;`verified` 后再失败 = reopen,刷新最近轮);新失败建条(编号沿用同一序列);在「速报」前追加 `## 第 N 轮记录(revision R · 日期)` 节,原地更新末尾速报。遇**无台账的旧格式报告** → 按当前内容一次性补建台账再继续
- 台账写入权见模板 writer matrix:本 skill 建条与核销;`fixed` + 修复 commit 归 eo-implement 回写;用户当场裁决不修的项 → 状态置 `waived`(附原话要点,不阻塞归档);历史轮次节不改;轮次编号全文件单调递增,跨 revision 不清零
- 2. **status 回退**:结论不通过且当前 status 为 `reviewed`(review 先过、test 后翻车)→ **当场置回 `implementing`** 并联动刷新 stub(回退边,见 [../eo-shared/conventions.md](../eo-shared/conventions.md) §3)
+ 2. **status 回退**:结论不通过且当前 status 为 `reviewed`(review 先过、test 后翻车)→ **当场置回 `implementing`**(回退边,见 [../eo-shared/conventions.md](../eo-shared/conventions.md) §3)
3. **对话速报(硬性——缺速报 = 流程未完成)**,报告写盘后在对话最后输出:
```
结论:通过 / 不通过(失败 x 项)[第 N 轮 · revision R · 基线 <short-sha>]
⚠️ 复发:<ID> 第二次失败(无则省略此行)
失败用例:
1. <一句话> — <用例/文件>
未覆盖 AC:<AC-x(原因)>;全覆盖则省略此行
下一步:<回 /eo-implement 修复 / 可进入 /eo-review(尚未审码)/ 可进入 /eo-archive(已审过码)>
(详细报告见 <test.md 路径>)
```
每条一句话加定位,不在速报里展开分析;全绿时压缩为「结论 + 下一步」两行。
## 关键约束
- **禁止跨权**:严禁修改业务逻辑代码
- **不重写已覆盖项**:已有测试审计通过的 AC 不重复编写;独立性靠审计 + 独立执行保证,不靠重写
- **测试独立性**:用例独立运行,不依赖执行顺序
- **不修改 change 的内容**:AC/TODO 的文字不动——发现写漏/写偏记录到报告并建议回 /eo-implement(其流程含「确认后就地补 AC」;循环内问题不出循环)。**勾选 auto-heavy AC 是本 skill 的职权**(勾是验证结果的落点,不是改 change);light 项已由 implement 勾、manual 项归用户,两者都不碰
- **环境不归你所有**:探测复用、用完不停;按环境组合分组跑,不为单条 AC 反复起停
- **输入不只来自 AC**:跳过「读实现取输入」= 只验 AC 想到的路径,这正是重验证跑再多遍也漏缺陷的原因
- **证据完整**:关键场景必须有可验证的执行证据