mcpField
T
tdd

tdd

github.com/robsonrung测试与质量247 次安装1 天前更新
代码仓库

关于 tdd

tdd 是一种开发技能,指导以小步、测试先行的方式完成行为变更,适用于需要逐步验证失败情形、可观察行为和重构的编码工作。

主要功能

  1. 01先建立失败用例
  2. 02采用可逆小步迭代
  3. 03测试通过后再重构
  4. 04验证可观察行为
  5. 05报告改动与验证结果

适用场景

  1. 01通过失败测试修复行为
  2. 02修改前刻画旧代码行为
  3. 03在测试通过时进行重构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/robsonrung/rar-skills --skill tdd

安装后在 Claude Code 中输入/tdd确认已加载。

详细介绍

TDD — 测试优先执行

选择分支后,再选择模型。协调工作和确定性命令在调用权限范围内进行。在当前角色中应用此方法。它不会派发工作者。派发工作者时,请使用 shared/references/model-preview.md 及其唯一获批的路线快照。嵌套技能和运行器使用该快照,不再进行其他选择或派发工作者。

铁律

在修复请求的行为之前,先建立一个会失败的行为用例。 如果已捕获的失败能证明同一代码存在同一缺陷,就复用该失败。

  • 保留已有的有效工作。不要仅为改变代码历史的顺序而删除并重新创建代码。
  • 新测试通过,可能是在描述现有行为。它并不能证明缺少某种行为,也不能证明测试有误。使用相关失败或受控反例来确定它能检测到什么。

步骤 0 — 这是谁的代码?

对于未经测试的遗留代码中的高风险更改,应用 safe-incremental-coding 来补充缺失的特征描述。复用涵盖变更范围的现有行为证据和失败证据。如果已有这些保护措施,则直接继续。

循环

每次行为增量运行一个循环。让每次迭代都足够小,小到可以毫不惋惜地丢弃。

  1. 确定最小的可逆改动。 只增加一个调用方可见的行为,这是成本最低、可逆的学习步骤,应比直觉认为的还要小。如果无法用一句话说明结果,说明步骤太大;应拆分。选择时说出来:“这里最小的可逆改动是……”
  2. 先编写测试,预测失败,并确认它确实失败。 从调用方的角度表达代码应做什么。运行前,大声说出预期的失败;如果出现了不同的失败,你已经有所收获。
  3. 用最简单的方式让测试通过。 只写通过测试所需的最少代码;直接了当即可。这是战术步骤,不是设计步骤,暂时不要打磨。
  4. 在测试通过的状态下重构。 改进具体的设计问题,然后在进行下一次行为更改前运行受影响的测试。存在代码异味时,使用 clean-code 指出异味。必须成立的内部不变量应使用断言:断言是可执行文档,断言失败意味着存在 Bug,而不是一种需要捕获并忽略的情况。
  5. 集成连贯的增量。 让每个增量都小且通过测试。只有在用户或调用方授权时才提交;根据已完成的行为和通过的检查来选择提交边界,而不是根据计时器。

控制变量

只有能够将效果归因于某个步骤时,你才能从中学习:

  • 一次只做一项更改。 不要将重构与行为更改、配置调整捆绑在一起。
  • 间歇性测试属于失败,绝不能重跑后将其视为通过。
  • 避免巧合式编程。如果代码通过了,要弄清楚原因。
  • 绝不钻检查的空子。 禁止为了让测试通过而删除、跳过、弱化、缩小测试范围或用 Mock 规避测试;如果能证明测试实现有误,可在修复权限范围内更正。若要更改已接受的产品契约,则需要作出决策(shared/references/engineering-rules.md,契约完整性)。

测试编写标准

编写时遵循的规则。当现有测试的价值存疑时,由 test-lens 做判断;以下是编写测试时应遵循的标准,确保它永远不必判定你不合格。

  • 风格排序:基于输出(断言纯函数的返回值)> 基于状态 > 基于通信(模拟对象)。通过函数式核心(纯决策)加上可变外壳(精简的 I/O 胶水代码),推动代码采用基于输出的方式。
  • 断言可观察行为,绝不检查实现细节。绝不断言对桩对象的调用。
  • AAA — Arrange / Act / Assert,各一个 — 使用描述领域行为的语句命名:delivery_with_a_past_date_is_invalid,而不是 testIsValid_case3。
  • 难以编写的测试是设计异味——改进设计,而不是测试。
  • 重构检验标准:如果用一个完全不同的实现替换当前实现,这个测试仍然有效吗? 应该有效。

设计与风险提示

选择测试和重构方案时使用以下提示;每次集成前无需再进行一轮评审。

  1. Farley 的五个杠杆:模块化、内聚性、关注点分离、抽象、低耦合。在变更范围内处理这些属性的回归问题。
  2. “如果……会怎样?”:选择此行为可能暴露的失败场景,例如无效输入、依赖项故障、并发、安全问题或资金损失。复用验收约定中已有的场景和决策。

每步输出约定

每次循环迭代(或一个连贯的批次)后,报告:

  1. changed:编辑了什么。
  2. behavior:代码现在新增了什么行为,或保留了什么行为。
  3. risk_guarded:此步骤中的测试现在防护的主要设计或数据风险。
  4. verification:运行的测试或检查,或无法运行的原因。

路由

  • 持久化状态、队列、重试、迁移、外部 API → 复用已批准的 data-systems-coding-lens 发现结果。仅在出现尚未覆盖的数据风险或设计表面发生变化时运行此 lens,而非每次循环迭代前都运行。
  • 重构步骤中使用 clean-code 处理异味术语和命名。
  • 判断现有测试是否值得保留时使用 test-lens。
  • 循环中出现无法解释的失败时使用 diagnose。已查明原因的失败或回归留在当前循环中处理;使用现有证据,而不是启动第二轮调查。

注意事项

  1. 巨型步骤——写了半天代码才第一次运行测试。
  2. 先实现后测试——贴合现有代码编写的测试可能会漏掉预期行为。根据验收约定和相关反例检查测试;保留有效的工作成果。
  3. 追逐覆盖率——覆盖率是循环的副产品,绝不是目标。
  4. 通过测试后再过度设计——在不安全时进行设计;设计应放在重构步骤中。
  5. “没时间测试”——速度与质量之间不存在取舍;降低返工才是提速之道。
  6. 不要扩大范围去清理无关代码。
  7. 不要仅仅因为分层、服务或辅助函数听起来整洁,就添加它们。
  8. 如果修复无害的局部耦合所增加的间接层多于清晰度,就不要削弱这种耦合。
  9. 设计需要转向时,通过小步重构实现从通过测试到继续通过测试——改变主意是有成本的;此前小步前进带来的速度,正是为了支付这笔成本。
  10. 不要引用或还原此技能所提炼的书籍中的原文。

评论

支持 Markdown