spec-author-tests
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAuthor Tests From a Spec
根据规格编写测试
Turn behaviours, invariants, decision-table rows, and flow transitions into tests. The spec is the source of truth; the tests demonstrate it.
Format authority: . Framework, patterns, and file conventions: .
references/spec-format.md.engineering/config.yaml将行为规则、不变量、决策表行项及流程转换逻辑转化为测试用例。规格是唯一依据,测试用例用于验证规格要求。
格式规范参考:。框架、模式及文件约定:。
references/spec-format.md.engineering/config.yamlWhen to use
使用场景
- "Write tests from this spec."
- Filling gaps found.
spec-assess-coverage - Proving a wizard's navigation and recovery paths.
Not this skill: assessing what's missing (), a regression test for a reported bug (), deciding a test is worth writing ( — apply that first).
spec-assess-coveragebug-regression-red-greenwrite-tests- 当用户提出“根据此规格编写测试”时
- 填补spec-assess-coverage识别出的测试覆盖率缺口时
- 验证向导的导航流程与异常恢复路径时
不属于此技能的场景:评估缺失内容(spec-assess-coverage)、针对已报告bug编写回归测试(bug-regression-red-green)、判断某功能是否值得编写测试(write-tests — 需先调用该技能)。
Workflow
工作流程
1. Select the surface
1. 确定测试范围
Confirm which behaviours, invariants, rows, and transitions are in scope. Default to what reported uncovered, then drop anything would refuse — types already cover it, I said not to test it, it is unscheduled, or it is an implementation detail. For behavioural guards, both branches are separate tests.
spec-assess-coveragewrite-tests确认需要覆盖的行为规则、不变量、决策表行项及流程转换逻辑。默认以spec-assess-coverage报告的未覆盖内容为基础,排除write-tests技能判定无需测试的内容——如已由类型系统覆盖、用户明确要求不测试、未排期的功能,或属于实现细节的内容。对于行为分支判断,需为每个分支单独编写测试用例。
2. Pick the layer
2. 选择测试层级
Unit for pure logic; integration where it crosses the database, auth, or multiple steps. Follow the location and naming conventions in .
config.yaml纯逻辑功能采用单元测试;涉及数据库、认证或多步骤交互的功能采用集成测试。遵循中定义的文件位置与命名规范。
config.yaml3. Write tests named after the requirement
3. 以需求为命名依据编写测试
Name each test after the documented intent, and cite the ID:
B5 — a partially paid invoice can be refunded up to the amount received
F1.T3 — validation failure returns to upload with the reason shown
Decision table row 4 — an expired grace period marks the payment overdueA future reader must be able to go from a failing test to the thing it was protecting without reading the implementation. This is why the naming matters more than usual.
Assert the documented outcome, not what the code currently returns. A test written by observing current behaviour proves the code does what it does — which is worth nothing.
每个测试用例的名称需对应文档化的需求意图,并标注需求ID:
B5 — 已部分支付的发票可按已收款金额退款
F1.T3 — 验证失败时返回上传页面并显示失败原因
决策表第4行 — 宽限期到期标记付款逾期未来的维护者必须能够通过失败的测试直接定位到对应的需求,无需查看实现代码。这也是测试命名比往常更重要的原因。
断言需基于文档化的预期结果,而非当前代码的实际返回值。仅通过观察当前行为编写的测试,只能证明代码“做了它现在做的事”——毫无价值。
4. Stub what isn't built
4. 为未实现功能编写测试桩
Where the spec describes behaviour that doesn't exist yet (🔵, or 🟡 for the missing part), write a pending test using the framework's todo or skip marker — never a passing empty test. Each carries a traceability comment naming the ID and why it's pending:
// TODO B7 — future: notification on late completion. Spec: specs/<path>.mdPending tests are the honest record of the gap and they surface the moment the work lands.
当规格描述的功能尚未实现时(标记为🔵,或功能部分缺失标记为🟡),使用测试框架的todo或skip标记编写待处理测试——绝不能编写空的通过测试。每个待处理测试需添加追溯注释,标注需求ID及待处理原因:
// TODO B7 — 未来需求:延迟完成时发送通知。规格文档:specs/<path>.md待处理测试是缺口的真实记录,一旦功能开发完成,就能立即暴露出来。
5. Halt on disagreement — do not reconcile
5. 出现分歧时立即停止——切勿调和
If the implementation appears to contradict the spec, stop. Do not change the test to match the code, and do not change the code to match the spec.
Report: the ID, what the spec says, what the code does, and both possibilities — spec is stale (→ ) or code is wrong (→ ). Let me decide.
spec-maintain-on-shipbug-regression-red-greenThis is the rule that keeps the spec meaningful. A skill that silently reconciles turns the spec into a description of whatever was built.
若实现代码与规格描述存在矛盾,立即停止操作。不要修改测试以匹配代码,也不要修改代码以匹配规格。
需上报:需求ID、规格描述的内容、代码的实际行为,以及两种可能性——规格已过期(→ 调用spec-maintain-on-ship)或代码存在错误(→ 调用bug-regression-red-green),由用户决定后续处理方式。
这是保证规格有效性的核心规则。若技能自动调和分歧,规格将沦为对已实现内容的描述,失去指导意义。
6. Run and hand back
6. 运行测试并交付
Run the tests. New tests against implemented behaviour should pass; if one fails, that's a step-5 disagreement, not a test to adjust until green.
Report: tests written, pending stubs and why, disagreements found, and any behaviour you couldn't test with a reason.
运行测试用例。针对已实现功能的新测试应通过;若测试失败,属于步骤5的分歧情况,而非需要调整至通过的测试。
需上报:已编写的测试数量、待处理测试桩及其原因、发现的分歧点,以及无法测试的行为及原因。
Quality gate
质量门禁
- Every test names the spec ID it demonstrates.
- Assertions come from the spec, not from observed behaviour.
- Both branches of each guard tested separately.
- Unbuilt behaviour stubbed as pending with traceability, never as passing empty tests.
- Disagreements halted and reported, never reconciled.
- Tests run; failures explained rather than tuned away.
- 每个测试用例均标注了对应的规格ID
- 断言基于规格要求,而非观察到的当前行为
- 每个分支判断的两个分支均单独测试
- 未实现功能以带追溯信息的待处理测试桩标记,而非空的通过测试
- 分歧点已上报并停止操作,未进行调和
- 已运行测试;失败原因已说明,而非强行调整至通过
Anti-patterns
反模式
- Writing the test by running the code. Proves only that the code does what it does.
- Adjusting an assertion until it passes. That's the disagreement case, and it's the one worth catching.
- Editing the spec to match the code mid-task.
- One test covering five rows. Row-level naming is what makes a decision table auditable.
- Empty passing tests for unbuilt behaviour. They read as coverage.
- Filling every uncovered ID. decides whether the ID earns a test.
write-tests
- 通过运行代码编写测试:仅能证明代码“做了它现在做的事”
- 调整断言直至测试通过:这属于分歧场景,正是需要捕捉的问题
- 在任务中修改规格以匹配代码
- 一个测试覆盖五个决策表行项:行级命名是决策表可审计性的关键
- 为未实现功能编写空的通过测试:会造成覆盖率达标的假象
- 填补所有未覆盖的需求ID:是否需要编写测试需由write-tests技能判定
Related skills
相关技能
- — whether this test should exist
write-tests - — what needs writing
spec-assess-coverage - — when the spec turned out to be stale
spec-maintain-on-ship - — when the code turned out to be wrong
bug-regression-red-green
- — 判断某测试是否有必要存在
write-tests - — 识别需要编写测试的内容
spec-assess-coverage - — 当规格已过期时使用
spec-maintain-on-ship - — 当代码存在错误时使用
bug-regression-red-green