SuperAPI AI 工具集

test-driven-development

测试与质量

查看项目

更新于 10-16 04:17

技能介绍

该技能名为 Test-Driven Development(TDD),是一套严格的测试驱动开发执行规范,核心是 RED-GREEN-REFACTOR 循环,且“无例外”。其核心原则是:如果你没有亲眼看到测试失败,你就不知道它是否在测试正确的东西。违反规则的文字就是违反规则的精神。

用途与适用场景

该技能适用于:新功能、缺陷修复、重构、行为变更。例外情况(需询问人类搭档):一次性原型、生成的代码、配置文件。文档明确指出,若你想着“就这一次跳过 TDD”,那就是在合理化,应当停止。

铁律

没有失败的测试,就不写生产代码。若在测试之前写了代码,必须删除并重新开始。没有例外:不要把它留作“参考”,不要在写测试时“改编”它,不要看它。删除就是删除。必须从测试重新实现。

RED-GREEN-REFACTOR 循环

RED:写一个最小的失败测试,描述期望行为。要求:一个行为、清晰的名称、真实代码(除非不可避免,否则不用 mock)。

验证 RED:强制且不可跳过。运行项目测试命令,针对特定测试文件。确认:测试失败(不是报错)、失败信息符合预期、失败原因是功能缺失(不是拼写错误)。若测试通过,说明你在测试已有行为,需修正测试;若测试报错,修复错误并重跑,直到它正确失败。

GREEN:写最简代码让测试通过。不要添加功能、重构其他代码或超出测试范围“改进”。

验证 GREEN:强制。运行项目测试命令,确认:测试通过、其他测试仍通过、输出干净(无错误、警告)。若测试失败,修代码而非改测试;若其他测试失败,立即修复。

REFACTOR:仅在绿灯后进行。消除重复、改进命名、提取辅助函数。保持测试绿灯,不添加行为。

重复:为下一个功能写下一个失败测试。

好测试的标准

最小:只测一件事,名称中有“and”就拆分。清晰:名称描述行为。展示意图:演示期望的 API。

为什么顺序重要

文档反驳了多种常见借口:

  • “我之后写测试来验证它能工作”:之后写的测试会立即通过,立即通过证明不了任何事——可能测错东西、可能测实现而非行为、可能漏掉你忘记的边界情况、你从未看到它抓住 bug。测试先行强制你看到测试失败,证明它确实在测试某些东西。
  • “我已经手动测试了所有边界情况”:手动测试是临时的,没有记录、代码变更后无法重跑、压力下容易忘记、"我试的时候能工作"不等于全面。自动化测试是系统性的。
  • “删除 X 小时的工作是浪费”:沉没成本谬误。时间已经过去。现在的选择是:删除并用 TDD 重写(再花 X 小时,高置信度),或保留并在之后加测试(30 分钟,低置信度,可能有 bug)。保留无法信任的代码才是技术债。
  • “TDD 是教条的,务实意味着变通”:TDD 就是务实的——在提交前发现 bug(比事后调试快)、防止回归、记录行为、支持重构。"务实"的捷径等于在生产环境调试,更慢。
  • “之后写测试达到同样目标——是精神不是仪式”:不对。之后写测试回答“这做了什么?”,测试先行回答“这应该做什么?”。之后写测试受实现偏见影响,你测试的是你构建的,不是要求的。

常见合理化与反驳

文档列出常见借口及现实:太简单不用测(简单代码也会坏,测试只需 30 秒);我之后测(立即通过证明不了什么);之后测达到同样目标(之后测=“这做什么”,先测=“这应该做什么”);已经手动测过(临时不等于系统,无记录、无法重跑);删除 X 小时浪费(沉没成本谬误,保留未验证代码是技术债);留作参考先写测试(你会改编它,那就是之后测,删除就是删除);需要先探索(可以,扔掉探索,从 TDD 开始);测试难=设计不清(听测试的,难测=难用);TDD 会拖慢我(TDD 比调试快,务实=测试先行);手动测试更快(手动不证明边界情况,每次变更都要重测);现有代码没测试(你在改进它,为现有代码加测试)。

红旗信号——停止并重新开始

代码先于测试、测试在实现之后、测试立即通过、无法解释测试为何失败、测试“稍后”添加、合理化“就这一次”、“我已经手动测过”、“之后测达到同样目的”、“是精神不是仪式”、“留作参考”或“改编现有代码”、“已经花了 X 小时,删除浪费”、“TDD 教条,我务实”、“这次不同因为……”。所有这些都意味着:删除代码,用 TDD 重新开始。

示例:缺陷修复

Bug:空邮箱被接受。RED:写测试“拒绝空邮箱”,断言 result.error == "Email required"。验证 RED:运行,FAIL: expected "Email required", got None。GREEN:在 submit_form 中检查邮箱为空或去空格后为空,返回错误。验证 GREEN:PASS。REFACTOR:如需要,为多个字段提取验证。

验证清单

标记工作完成前:每个新函数/方法都有测试;在实现前看到每个测试失败;每个测试因预期原因失败(功能缺失,不是拼写错误);为每个测试写最简代码;所有测试通过;输出干净(无错误、警告);测试使用真实代码(仅在不可避免时用 mock);覆盖边界情况和错误。无法勾选所有项?你跳过了 TDD,重新开始。

卡住时

不知道如何测试:写期望的 API,先写断言,询问人类搭档。测试太复杂:设计太复杂,简化接口。必须 mock 一切:代码太耦合,使用依赖注入。测试设置巨大:提取辅助函数,仍复杂则简化设计。

调试集成

发现 bug?写一个复现它的失败测试,遵循 TDD 循环。测试证明修复并防止回归。永远不要在没有测试的情况下修复 bug。

与规格驱动工作流集成

该技能是规格驱动实现第 5 阶段(执行)的核心。在任务分解(第 4 阶段):每个任务结构为 RED → GREEN → REFACTOR,任务包含明确的测试先行步骤。在执行(第 5 阶段):每个任务遵循 TDD 循环,将 RED、GREEN、REFACTOR 子任务标记为完成,每个阶段后提交:test: Add test for [functionality]、feat: Implement [functionality]、refactor: Optimize [component]。质量门:继续前所有测试必须通过;没有测试就没有代码;提交前由代码质量技能审查。

最终规则

生产代码 → 测试存在且先失败。否则 → 不是 TDD。未经人类搭档许可,无例外。