SuperAPI AI 工具集

tdd

编程与开发

查看项目

更新于 10-16 02:09

技能介绍

TDD — 测试先行执行

用途

该技能用于通过红-绿-重构循环实现行为。当请求测试先行执行,或编码工作流选择该方式时应用。它不派发 worker;如需 worker 派发,使用 shared/references/model-preview.md 及其唯一获批的路由快照。嵌套技能与 runner 直接消费它,无需再次选择或 worker。

铁律

在修复所请求的行为之前,先建立一个失败的行为用例。当捕获到的失败能证明同一代码上的同一缺陷时,可复用该失败。

保留已有的有效工作。不要仅仅为了改变历史顺序而删除并重建代码。

一个通过的新测试可以刻画既有行为,但不能证明缺失的行为,也不能证明该测试是错的。使用相关的失败或受控反例来确定它检测的是什么。

第 0 步 — 这是谁的代码?

对未测试遗留代码进行有风险的改动时,应用 safe-incremental-coding 来补充缺失的特征化。复用覆盖改动面的既有行为证据与失败证据。若该保护已存在,则直接进行。

循环

每个行为增量运行一次循环。每次通过都保持足够小,小到丢弃也不心疼。

框定最小的可逆动作。一个调用方可见的行为增量——最廉价的可逆学习步骤,比感觉自然的粒度更小。如果你无法用一句话陈述结果,说明这一步太大,需拆分。在选择时说出:“这里最小的可逆动作是……”。

先写测试,预测失败,看着它失败。从调用方视角表达代码应该做什么。运行前说出预期失败——不同的失败已经教会了你一些东西。

用最简单的方式达到绿灯。用能通过的最少代码;朴素即可。这是战术步骤,不是设计步骤——此时不要打磨。

在绿灯下重构。改进一个具体的设计问题,然后在下一个行为变更前运行受影响的测试。当存在坏味道时,应用 clean-code 来命名它。在必须成立的地方断言内部不变量:断言是可执行的文档,其失败是 bug,而不是要捕获并忽略的条件。

整合连贯的增量。保持每个增量小而通过。仅在用户或调用方授权时提交;用已完成的行为和通过的检查来选择边界,而不是用计时器。

控制变量

只有能归因某一步的效果,才能从中学到东西:

一次只改一件事。绝不把重构与行为变更、配置调整捆绑在一起。

间歇性失败的测试就是失败,绝不是可以重跑通过的。

避免靠巧合编程。如果代码通过,要知道为什么。

绝不糊弄检查。为达到绿灯而删除、跳过、弱化、收窄或 mock 掉测试是被禁止的;在修复权限内纠正已被证实的测试实现错误。对已接受产品契约的变更需要决策(shared/references/engineering-rules.md,Contract integrity)。

写测试的标准

写时规则。当既有测试的价值存疑时,test-lens 是裁判;以下是你要遵循的标准,以免被它判定为不合格。

风格排序:基于输出(断言纯函数的返回值)> 基于状态 > 基于通信(mock)。通过函数式核心(纯决策)包裹可变外壳(薄 I/O 胶水)把代码推向基于输出。

断言可观察行为,绝不断言实现细节。绝不断言对 stub 的调用。

AAA——Arrange / Act / Assert,各一个——以领域行为语句命名:delivery_with_a_past_date_is_invalid,而不是 testIsValid_case3。

难以编写的测试是设计坏味道——修设计,而不是修测试。

重构试金石:如果实现被换成完全不同的一个,这个测试是否仍然有效?它应该有效。

设计与风险提示

在选择测试和重构时使用这些提示;它们不要求每次整合前再做一次评审。

Farley 的五个杠杆:模块化、内聚、关注点分离、抽象、低耦合。在改动范围内处理这些属性的回归。

“如果……会怎样?”:选择该行为暴露的失败用例,例如无效输入、依赖失败、并发、安全或金钱损失。复用验收契约中已有的用例与决策。

每步输出契约

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

changed:编辑了什么。

behavior:代码现在做了什么之前没做的事,或行为被保留。

risk_guarded:这一步的测试现在守护的主要设计或数据风险。

verification:运行的测试或检查,或为何无法运行。

路由

存储状态、队列、重试、迁移、外部 API → 复用已获批的 data-systems-coding-lens 发现。仅对未覆盖的数据风险或变更的设计面运行该 lens,而不是在每次循环迭代前运行。

在重构步骤中应用 clean-code 获取坏味道词汇与命名。

在判断既有测试是否值得保留时应用 test-lens。

当循环中途出现无法解释的失败时应用 diagnose。已理解的红色或回归留在当前循环中;使用既有证据,而不是启动第二次调查。

常见陷阱

巨型步骤——在首次运行测试前写了半天的代码。

事后补测——为既有代码量身定做的测试可能错过预期行为。对照验收契约和相关反例检查它;保留有效工作。

追逐覆盖率——覆盖率是循环的副作用,绝不是目标。

绿灯下镀金——在不安全时做设计;设计属于重构步骤。

“没时间测试”——不存在速度与质量的权衡;更快的方法就是保持低返工。

不要扩大范围去清理无关代码。

不要因为听起来整洁就添加层、服务或辅助工具。

当补救带来的间接性多于清晰度时,不要弱化无害的局部耦合。

当设计需要转向时,以小步重构在绿灯到绿灯之间调整——改变主意是有代价的;这笔账正是小步早先为你买来的速度。

不要引用或重建本技能所提炼书籍的原文。