tdd

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

tdd

TDD

The agent codes better with a tight feedback loop than with a long specification. A failing test is the tightest loop there is: it states the target, and the target either goes green or it does not.
Agent 在紧密反馈循环中比面对冗长规范能编写出更好的代码。失败测试是最紧密的反馈循环:它明确目标,而目标要么变为 Green,要么没有。

The loop

循环

  1. Red. Write one failing test that states the next slice of behavior. Run it. Confirm it fails for the right reason - a test that passes before you write the code is testing nothing. If it errors instead of failing on the assertion, fix the test setup first.
  2. Green. Write the least code that makes the test pass. Not the general solution, not the abstraction - the minimal move. Run the test. Green.
  3. Refactor. Now clean up with the test as a net: remove duplication, name things, simplify. Re-run after every edit. Behavior is frozen; only the shape changes.
  4. Repeat for the next slice. Small slices. The rate of feedback is the speed limit - never take on a step too big to hold a single test.
  1. Red. 编写一个失败的测试,明确下一小段行为。 运行测试。确认它因正确的原因而失败——在你编写代码前就通过的测试没有验证任何东西。如果测试是报错而非断言失败,应先修复测试设置。
  2. Green. 编写能让测试通过的最少代码。不是通用解决方案,也不是抽象层——只做最小改动。运行测试。变为 Green。
  3. Refactor. 现在以测试作为安全网进行清理:消除重复、合理命名、简化实现。每次编辑后都重新运行测试。行为保持不变,改变的只有代码形态。
  4. 针对下一小段行为重复上述过程。小步推进。反馈速度就是速度上限——不要承接大到单个测试无法容纳的步骤。

What makes a test worth writing

什么样的测试值得编写

  • Tests behavior, not implementation. Assert on the observable result, not on which private method got called. A test that breaks on every refactor is a liability.
  • One reason to fail. Each test pins one behavior. When it goes red you should know what broke without reading the body.
  • Real seams, minimal mocks. Mock at the system boundary (network, clock, filesystem), not internal collaborators. A test that mocks the thing under test asserts nothing.
  • No tautologies. A test that restates the implementation (
    expect(x).toBe(x)
    after setting
    x
    ) verifies nothing. Assert the value the behavior should produce.
  • 测试行为,而非实现。 断言可观察的结果,而不是断言调用了哪个私有方法。每次重构都会失效的测试是一种负担。
  • 只有一个失败原因。 每个测试固定一种行为。当它变为 Red 时,你无需阅读测试主体就知道哪里出了问题。
  • 使用真实的接缝,最少使用 mock。 在系统边界(网络、时钟、文件系统)处使用 mock,而不是针对内部协作者。mock 被测对象本身的测试没有验证任何东西。
  • 不要同义反复。 重复实现逻辑的测试(设置
    x
    后使用
    expect(x).toBe(x)
    )没有验证任何东西。应断言行为应产生的值。

When to reach for it

何时使用

Reach for TDD when the behavior is specifiable and a test can pin it: business logic, parsers, state machines, bug fixes (write the failing case first, then fix). Skip it for pure exploration, throwaway spikes, and layout-only UI where a test asserts nothing a human would not eyeball.
当行为可以被明确描述且测试能够将其固定时,使用 TDD:业务逻辑、parser、状态机、缺陷修复(先编写失败用例,再修复)。对于纯探索、一次性 spike,以及仅涉及布局且测试无法断言任何人工肉眼可判断内容的 UI,则无需使用。

Output contract

输出约定

Show each red-green transition, not just the final green. If a test is hard to write, say what the difficulty reveals about the design - untestable code is usually badly-seamed code, and that is a finding, not an obstacle.
展示每一次 Red-Green 转换,而不只是最终的 Green。如果某个测试难以编写,应说明这一难点揭示了哪些设计问题——不可测试的代码通常意味着接缝设计不佳,这是一项发现,而不是障碍。