tdd
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTest-Driven Development
测试驱动开发
TDD is the red → green loop. This skill is the reference that makes that loop produce tests worth keeping: what a good test is, where tests go, the anti-patterns, and the rules of the loop. Every section applies on every cycle: consult them before and during the loop, not after.
When exploring the codebase, read (if it exists) so test names and interface vocabulary match the project's domain language, and respect ADRs in the area you're touching.
GLOSSARY.mdTDD 是 red → green 循环。这个 skill 是让该循环产出值得保留的测试的参考指南:什么是好的测试、测试应放在哪里、反模式,以及循环规则。每一节都适用于每个循环:在循环之前和期间查阅,而不是之后。
探索代码库时,如果存在 ,请阅读它,以确保测试名称和接口词汇与项目的领域语言一致,并遵循你正在修改区域的 ADR。
GLOSSARY.mdWhat a good test is
什么是好的测试
Tests verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't. A good test reads like a specification: "user can checkout with valid cart" tells you exactly what capability exists, and it survives refactors because it doesn't care about internal structure.
See tests.md for examples and mocking.md for mocking guidelines.
测试通过公共接口验证行为,而不是实现细节。代码可以完全改变;测试不应改变。好的测试读起来像规格说明:“用户可以使用有效购物车完成结账”准确告诉你存在什么能力,而且它能经得起重构,因为它不关心内部结构。
有关示例,请参阅 tests.md;有关 mocking 指南,请参阅 mocking.md。
Seams: where tests go
Seam:测试放在哪里
A seam is the public boundary you test at: the interface where you observe behavior without reaching inside. Tests live at seams, never against internals.
Test only at pre-agreed seams. Before writing any test, write down the seams under test and confirm them with the user. No test is written at an unconfirmed seam. You can't test everything, so agreeing the seams up front is how testing effort lands on the critical paths and complex logic instead of every edge case.
Ask: "What's the public interface, and which seams should we test?" Give each proposed seam a one-line note on what it catches and what it misses.
When the shape of that interface is itself in question (how deep the module is, where the seam belongs, what the interface should expose), call the Skill tool with "codebase-design" for the vocabulary. It is the shared source of the module, interface, depth, seam, adapter, leverage and locality terms, and it is a reference to consult, not a session to run.
Seam 是你进行测试的公共边界:你可以在该接口观察行为,而无需进入内部。测试应位于 seam 处,绝不针对内部实现进行测试。
只在预先约定的 seam 处进行测试。 编写任何测试之前,先列出待测试的 seam 并与用户确认。未经确认的 seam 处不编写任何测试。你无法测试一切,因此,预先约定 seam 是将测试投入集中到关键路径和复杂逻辑上,而不是覆盖每个边缘情况的方法。
询问:“公共接口是什么,应该测试哪些 seam?”为每个建议的 seam 用一行说明它能捕获什么、不能捕获什么。
当该接口本身的形态存在疑问时(模块应有多深、seam 应位于何处、接口应暴露什么),使用 Skill 工具并传入“codebase-design”以查阅相关词汇。它是 module、interface、depth、seam、adapter、leverage 和 locality 等术语的共享来源,应当作为参考资料查阅,而不是要运行的会话。
Anti-patterns
反模式
- Implementation-coupled: mocks internal collaborators, tests private methods, or verifies through a side channel (querying the database instead of using the interface). The tell: the test breaks when you refactor but behavior hasn't changed.
- Tautological: the assertion recomputes the expected value the way the code does (, a snapshot derived by hand the same way, a constant asserted equal to itself), so it passes by construction and can never disagree with the code. Expected values must come from an independent source of truth: a known-good literal, a worked example, the spec.
expect(add(a, b)).toBe(a + b) - Horizontal slicing: writing all tests first, then all implementation. Bulk tests verify imagined behavior: you test the shape of things rather than user-facing behavior, the tests go insensitive to real changes, and you commit to test structure before understanding the implementation. Work in vertical slices instead: one test → one implementation → repeat, each test a tracer bullet that responds to what the last cycle taught you.
- 与实现耦合:mock 内部协作者、测试私有方法,或通过旁路通道进行验证(直接查询数据库,而不是使用接口)。识别信号是:行为没有变化,但重构后测试却会失败。
- 同义反复:断言以与代码相同的方式重新计算预期值(、以相同方式手工推导出的快照、与自身相等的常量),因此它必然通过,永远不可能与代码产生分歧。预期值必须来自独立的事实来源:已知正确的字面值、推演示例或规格说明。
expect(add(a, b)).toBe(a + b) - 水平切片:先写完所有测试,再写完所有实现。批量测试验证的是_想象中的_行为:测试关注事物的_形状_而非用户可见行为,测试对真实变化不敏感,而且在尚未理解实现之前就锁定了测试结构。应改用纵向切片:一个测试 → 一份实现 → 重复;每个测试都是一颗 tracer bullet,用于响应上一个循环所揭示的信息。
Rules of the loop
循环规则
- Red before green. Write the failing test first, then only enough code to pass it. Don't anticipate future tests or add speculative features.
- One slice at a time. One seam, one test, one minimal implementation per cycle.
- Refactoring is not part of the loop. It belongs to the review stage (see the skill), not the red → green implementation cycle.
code-review
- 先 red,后 green。 先编写失败的测试,然后只编写刚好能让它通过的代码。不要预判未来需要的测试,也不要添加推测性功能。
- 每次只做一个切片。 每个循环只处理一个 seam、一个测试和一份最小实现。
- 重构不属于这个循环。 重构属于审查阶段(参见 skill),而不是 red → green 实现循环的一部分。
code-review