tdd
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTest-Driven Development
测试驱动开发(TDD)
TDD is the red → green → refactor 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.
CONTEXT.mdTDD 遵循红→绿→重构的循环流程。本技能是确保该循环能产出值得保留的测试的参考指南:包括什么是优质测试、测试应聚焦的边界、测试反模式,以及循环流程的规则。每个环节的内容都适用于每一轮循环——请在循环开始前及过程中参考,而非事后查阅。
在探索代码库时,请阅读(如果存在),确保测试名称和接口术语与项目的领域语言一致,并遵循你所修改区域的ADRs(架构决策记录)。
CONTEXT.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 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
测试边界(Seams)——测试应聚焦的位置
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 — 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?"
Seam是指你进行测试的公共边界:即无需深入内部即可观察行为的接口。测试应聚焦于Seam,绝不应针对内部实现。
仅在预先约定的Seam处进行测试。在编写任何测试之前,请写下要测试的Seam并与用户确认。不得在未确认的Seam处编写测试。你无法测试所有内容——预先约定Seam能确保测试工作聚焦于关键路径和复杂逻辑,而非每个边缘情况。
可以询问:“公共接口是什么?我们应该测试哪些Seam?”
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 for the expected reason. Write the failing test first and run it. Confirm that it fails because the requested behavior is absent, not because the test is broken.
- Green with the minimum change. Write only enough production code to pass the new test. Don't anticipate future tests or add speculative features.
- Refactor while green. Improve the design immediately after green and before the next red. Keep behavior unchanged and rerun the focused tests after each small transformation.
- One slice at a time. One seam, one test, one minimal implementation per cycle.
- Keep slices releasable. Do not leave the branch with a known failing test, a half-migrated interface, or production behavior that depends on a later slice.
- Escalate large refactors. If a refactor cannot stay small and behavior-preserving, stop the loop and plan it as separate work with characterization tests. Use after the completed slices; review complements refactoring and does not replace it.
$code-review
- 因预期原因变红。先编写失败的测试并运行它。确认测试失败是因为所需行为缺失,而非测试本身存在问题。
- 以最小改动变绿。仅编写足够使新测试通过的生产代码。不要提前为未来的测试做准备或添加推测性功能。
- 在变绿时重构。变绿后立即优化设计,再进入下一轮变红环节。保持行为不变,每次小改动后重新运行聚焦的测试。
- 一次处理一个切片。每轮循环仅处理一个Seam、一个测试、一个最小实现。
- 保持切片可发布。分支中不得存在已知失败的测试、半迁移的接口,或依赖后续切片的生产行为。
- 大型重构需升级处理。如果重构无法保持小规模且不改变行为,请停止循环,将其规划为单独的工作并编写特征测试。完成所有切片后使用;代码评审是重构的补充,而非替代。
$code-review