test-first-by-evidence

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Test First by Evidence

循证测试先行

Core principle. A test you did not watch fail proves nothing. It might test the wrong thing, and you would never know.
  • This is
    debugging-by-evidence
    pointed forward.
    One says no hypothesis before a command that reproduces. This one says no implementation before a test that failed.
  • The weight sits in Watch it fail. Everything else is what to do once the red is real.
  • You opened this in the middle of something. This is how to do that work, not a replacement for it. Name what you were doing before you start, and return to it when this is done.
核心原则:未亲眼见证失败的测试毫无意义。它可能测试了错误的内容,而你永远不会察觉。
  • 这是前瞻性的
    debugging-by-evidence
    (循证调试)
    。前者要求在复现问题的指令出现前不做假设,后者要求在测试失败前不进行实现。
  • 关键在于“观察其失败”。其他步骤都是在测试确实失败(红态)后的操作。
  • 你是在中途打开这份文档。这是完成当前工作的方法,而非替代原有工作。开始前明确你正在做的事情,完成后回到原工作。

The law

法则

NO PRODUCTION CODE WITHOUT A TEST YOU WATCHED FAIL
  • Code written before its test is unproven, and gets re-derived from a red rather than wrapped in a test that passes immediately.
  • Make it recoverable before removing anything. Discarding work the human has not agreed to discard is not yours to do.
  • A test that passes the first time you run it is not a test yet. It describes what the code already does.
  • A test that errors is not a red. An error is a broken test; a failure is a working test with nothing to satisfy it.
NO PRODUCTION CODE WITHOUT A TEST YOU WATCHED FAIL
  • 先于测试编写的代码未经验证,应从测试失败状态重新推导,而非直接用立即通过的测试包裹。
  • 在删除任何内容前确保可恢复。未经相关人员同意,不得丢弃已完成的工作。
  • 首次运行即通过的测试尚不能称为测试。它仅描述了代码已有的行为。
  • 报错的测试并非红态。报错是测试本身存在问题;失败是测试正常运行但没有内容能满足其断言。

Establish before the first test

编写首个测试前需明确的事项

  • Never ask what the repository answers. Three things settle the setup, and it holds all three.
    • The command this project already uses to run tests.
    • Where its tests live, and what a neighbouring test looks like.
    • The runner, so the failure output means something to you.
  • Read one nearby test before writing yours. Style is local, and a test that fights the local style is a second convention.
  • 不要询问仓库的默认设置。以下三点决定了测试环境,且项目已包含这些内容:
    • 项目已在使用的测试运行命令。
    • 测试文件的存放位置,以及相邻测试的样式。
    • 测试运行器,这样你能理解失败输出的含义。
  • 编写测试前先阅读一个相邻的测试。测试风格具有本地化特点,与本地风格相悖的测试会引入第二种规范。

Which rules to read

应阅读哪些规则

This table is a gate, not a checklist. Match the left column against what is in front of you.
  • One rule per row. Enter at the matched row, then follow the cycle in order.
  • A small change reads two rows. A new subsystem reads most of them. That difference is the point.
  • Where two rows match, read both. Under-reading costs a wrong test. Over-reading costs one file.
If you see...Read
a test about to be written, or one that passed on its first run
rules/watch-it-fail.md
a red you trust and code to write against it
rules/smallest-green.md
no obvious place for the test, or a choice between unit, integration, and end to end
rules/where-the-test-goes.md
mocks, fixtures, or assertions on calls rather than on results
rules/tests-that-cannot-lie.md
implementation that already exists with no test behind it
rules/code-written-first.md
a bug report, a stack trace, or a regression
rules/bug-fix-starts-red.md
a test that is hard to write, or needs everything mocked
rules/hard-to-test-is-a-signal.md
Discriminators.
  • Watch it fail against code written first. The first owns the normal path. The second owns the recovery when the order was already broken.
  • Where it goes against what makes it honest. Placement decides which seam. Honesty decides what it asserts once it is there.
  • Bug fix against watch it fail. A bug fix starts from a red that reproduces a defect. The general case starts from a red that describes a wish.
Default stance.
  • Write the test, run it, and watch it fail before writing any implementation.
  • Then write the least code that passes, and run the whole suite.
  • Never claim a phase you have not observed. A predicted failure is not a red.
此表格是指引而非检查清单。将左列内容与你当前的场景匹配。
  • 每行对应一条规则。从匹配的行进入,然后按顺序遵循循环步骤。
  • 小变更只需阅读两行。新子系统则需阅读大部分规则。这种差异正是关键所在。
  • 若两行都匹配,则阅读两者。阅读不足会导致测试错误,阅读过多仅多花一点时间。
若你遇到...阅读
即将编写的测试,或首次运行即通过的测试
rules/watch-it-fail.md
可信的红态测试,以及需针对其编写的代码
rules/smallest-green.md
测试位置不明确,或需在单元测试、集成测试、端到端测试间选择
rules/where-the-test-goes.md
使用Mock、测试数据或调用断言而非结果断言
rules/tests-that-cannot-lie.md
已存在的实现代码但无配套测试
rules/code-written-first.md
Bug报告、堆栈跟踪或回归问题
rules/bug-fix-starts-red.md
难以编写的测试,或需要大量Mock的测试
rules/hard-to-test-is-a-signal.md
区分要点
  • 观察失败 vs 代码先写:前者适用于常规流程,后者适用于顺序已被打破时的补救。
  • 测试位置 vs 测试真实性:位置决定测试的切入点,真实性决定测试的断言内容。
  • Bug修复 vs 观察失败:Bug修复从复现缺陷的红态测试开始,常规场景从描述需求的红态测试开始。
默认准则
  • 先编写测试,运行并观察其失败,再编写任何实现代码
  • 然后编写能通过测试的最少代码,并运行整个测试套件。
  • 切勿声称未观察到的阶段。预测的失败并非真实的红态。

Say which phase you are in

明确当前所处阶段

Report it every time. Each phase licenses only what it names.
PhaseMeansLicenses
NO-TEST
nothing written yetwriting one test, nothing else
RED
the test ran and failed for the stated reasonimplementation
GREEN
the test passes and so does everything elserefactoring
REFACTORED
duplication and names cleaned, still greenthe next test
  • Skipping a phase is the failure this skill exists to prevent.
  • RED
    requires a run you performed.
    Not a prediction that it would fail.
  • GREEN
    includes the rest of the suite.
    One new green and three new reds is not green.
每次都要说明。每个阶段仅允许对应操作。
阶段含义允许操作
NO-TEST
尚未编写任何内容编写一个测试,无其他操作
RED
测试已运行并因明确原因失败编写实现代码
GREEN
测试通过且其他所有测试也通过重构代码
REFACTORED
已清理重复代码和命名,测试仍为绿态编写下一个测试
  • 跳过阶段正是此技能要预防的错误
  • RED
    阶段要求你亲自运行测试
    。而非预测它会失败。
  • GREEN
    阶段包含整个测试套件
    。仅新增测试通过但其他三个测试失败不属于绿态。

Do not skip this when

以下情况请勿跳过此流程

  • The change is one line. A one-line change to the wrong line is still wrong.
  • The code is too simple to break. Simple code breaks. The test costs thirty seconds.
  • You already tested it by hand. Manual testing leaves no record and does not re-run.
  • You will add tests after. Tests written after pass immediately, which proves nothing about whether they can catch anything.
  • You are only exploring. Fine. Throw the exploration away and start again with a test.
  • 变更仅一行代码。一行代码改到错误位置仍然是错误的。
  • 代码过于简单不会出错。简单代码也会出错,编写测试仅需30秒。
  • 已手动测试过。手动测试没有记录且无法重复运行。
  • 打算之后再补测试。事后编写的测试会立即通过,无法证明它们能否发现问题。
  • 仅在进行探索性开发。可以,但请丢弃探索内容,重新从测试开始。

Routing

指引

  • The table above selects the rule. Read a selected rule in full, and say which one you opened, in one line.
  • Judging tests inside a change under review belongs to a review of the diff, not here.
  • Choosing a framework is a project decision, not this skill's.
  • A direct instruction from the user outranks anything here.
  • 上述表格选择对应规则。完整阅读选中的规则,并用一句话说明你打开了哪条规则。
  • 评审变更中的测试属于差异评审范畴,不属于此技能的内容。
  • 选择测试框架是项目层面的决策,不属于此技能的范畴。
  • 用户的直接指令优先级高于此处的所有内容