| name | tdd |
| description | Test-driven development with a red-green-refactor loop, built one vertical slice at a time. Use when user wants to build features or fix bugs with TDD, mentions 'red-green-refactor' / '测试驱动' / 'TDD' / '先写测试', or asks for integration tests. Refuses horizontal slicing (write all tests first then all code) as an anti-pattern. |
| argument-hint | <需求描述> |
Read `.claude/code-specs/{pkg}/{layer}/index.md`(按涉及文件映射)+ `core/specs/shared/glossary.md`。修改已有测试格式 / 重命名类 typo 可跳过。
Test-Driven Development
核心原则
测试验证行为,穿过 public interface;不测试 implementation 细节。代码可以全换,测试不应该换。
架构词汇用 core/specs/shared/architecture-language.md(Module / Interface / Seam / Depth / Adapter)。
好测试
integration 风格:穿过真实代码路径,经由 public API。描述系统做什么,不描述怎么做。像规范——"user can checkout with valid cart"一眼知道这条能力存在。refactor 后存活,因为它不关心内部结构。
坏测试
耦合到 implementation。mock 内部协作方、测私有方法、绕过 interface 用外部手段验证(比如直接查 DB 而不是走接口)。warning sign:refactor 会让测试红,但行为没变。重命名内部 function 测试就挂 = 它在测 implementation 不是行为。
反模式:Horizontal Slice
不要先写所有测试,再写所有实现。这是 horizontal slicing——把 RED 当"写所有测试",GREEN 当"写所有代码"。
产出烂测试:
- 批量写的测试测 想象中的 行为,不是 真实 行为
- 最终在测结构的形状(数据结构 / function signature)而非 user-facing 行为
- 对真实变化不敏感——行为坏了它还过,行为对了它反而挂
- outrun your headlights,提前对测试结构 commit,不理解 implementation
WRONG (horizontal):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
RIGHT (vertical):
RED→GREEN: test1→impl1
RED→GREEN: test2→impl2
...
正确做法:vertical slice via tracer bullet。一个 test → 一个 implementation → 重复。每个 test 响应你从上一轮学到的东西。刚写完代码,你最清楚哪些行为重要、怎么验证。
workflow
1. 规划
用 core/specs/shared/glossary.md 的项目词汇命名测试和 interface,让测试可读。
动手前:
问:"public interface 长什么样?哪些行为最重要?"
测试不完所有东西。和用户确认哪些行为最关键。重点覆盖 critical path 和复杂逻辑,不是每个 edge case。
2. Tracer Bullet
写一条测试,验证系统一件事:
RED: 写第一个行为的测试 → 失败
GREEN: 写最小代码让它过 → 通过
tracer bullet 证明 end-to-end 通路。
3. delta循环
剩下每个行为:
RED: 下一个测试 → 失败
GREEN: 最小代码让它过 → 通过
规则:
- 一次一个测试
- 只写够当前测试过的代码
- 不为未来测试提前写东西
- 测试聚焦可观察行为
4. Refactor
所有测试过后:
红灯下不要 refactor。先到绿。
每轮 checklist
红绿死锁
触发条件(满足任一即标 stuck_or_looping):
- 同一 RED test 经 3 次 GREEN 尝试 仍未通过(tracer bullet 容忍度高于 review loop,因此阈值取 3 而不是决策表 examples 里的
loop >= 2)
- 一次改动让 ≥ 2 个 之前绿的 test 变红,且 2 次 修正尝试仍未让全部回到绿
死锁里不要继续盲改实现(可能是 interface 设计错了 / 测试在测 implementation / module 太浅)。
调度归属(关键):本 skill 被 /workflow-execute --tdd 注入到 implementer subagent 时,implementer 检测到死锁 不得自起 codex,而是把 stuck_or_looping 信号 + RED 源码 + 3 次失败 diff + 失败信号回报 controller / 主会话;由 controller 唯一调 collaborating-with-codex --oracle-review;主会话直接驱动 tdd 时由主会话调。
contract:
- 调用 contract 见
core/specs/shared/codex-routing.md § Invocation Contract(TASK / CONTEXT / FILES / RISK_SIGNALS / NON_GOALS 必填),risk_signals: stuck_or_looping
- 输出:oracle read-only 建议(interface 是否要调整 / 测试是否应改写 / 是否要 deep module refactor)
- 落地:controller 把 oracle insight 回灌实现者(workflow-execute 路径下回灌 implementer subagent;主会话路径下主会话自己消费),再回 tracer bullet
- 降级:codex 不可用 → controller 向用户报告
codex_degraded + 降级原因(tdd 不维护持久 state),主会话自审是否要改 interface / 拆 test
与其他 skill 的关系
/workflow-execute 在执行阶段可调用本 skill 的 vertical slice 纪律
/fix-bug Phase 3 写修复时应走 red-green-refactor,而不是先改代码后补测试
/diagnose Phase 5 如果给出了 regression_seam,顺手进本 skill 写回归测试