测试驱动开发Skill:先写失败测试,再写最小实现,把"我觉得能跑"变成"我证明它能跑"
- 它是什么:一个把 TDD(测试驱动开发)铁律固化进 AI 编程流程的技能,核心是一条不可协商的规则——没有生产代码,除非先有失败测试。
- 它解决什么:AI 编码助手最大的问题不是写不出代码,而是写得太快、验证太少。代码先于测试、测试后补、测试一写就通过,这些都会让"测试"变成心理安慰而不是质量证据。
- 它的工作方式:强制走完 RED(写失败测试)→ 验证失败 → GREEN(最小代码)→ 验证通过 → REFACTOR(保持绿色地清理)的完整闭环,每一步都要看到真实运行结果。
- 它的特色:内置"常见合理化借口对照表"“红旗清单”“验证清单”,专门用来对抗"这次就先跳过吧"的自我说服。
- 适合谁:需要长期维护的项目的开发者、正在用 AI 大量生成代码的团队、以及想系统性补上测试短板的工程师。
1. 该技能叫什么?如何下载安装 AI 技能提升开发效率?
基本信息
| 项目 | 内容 |
|---|---|
| 中文名 | 测试驱动开发Skill |
| 英文名 | test-driven-development |
| 技能ID | 11822 |
| 触发时机 | 在编写实现代码之前,用于实现任何功能或修复错误时 |
| 核心主张 | 先写测试,看它失败,再写最小代码让它通过 |
它到底解决什么问题
传统开发(尤其是和 AI 协作时)最常见的流程是:描述需求 → AI 一次性给出完整实现 → 顺手补几个测试 → 测试全部通过 → 提交。
这个流程看起来高效,但存在一个致命的逻辑漏洞:后写的测试立即通过,什么也证明不了。它可能测错了对象、可能测的是实现细节而非行为、可能漏掉了你根本没想到的边界情况,而你从未看到它捕捉到任何一个错误。
这个技能就是把顺序掰回来:让测试先失败一次,用"失败"这个事实证明测试确实在测试某些东西。
一键安装的思路与步骤
- 确认安装前提:你需要一个支持"技能(Skill)机制"的 AI 编程助手或 Agent 运行环境。技能本质上是一段被注入到模型上下文中的方法论约束文件,因此环境必须支持加载外部技能。
- 找到安装入口:在所用工具的技能市场 / 技能目录 / 插件管理中检索技能英文名
test-driven-development或技能ID11822,选择安装并启用。具体入口位置、命令与安装方式以官方说明为准。 - 确认技能已加载:安装完成后,在会话中提出一个开发需求,观察 AI 的第一反应——如果它开始写实现代码,说明技能未生效;如果它先提出要写一个失败测试,并主动要求运行测试命令,说明技能已正常加载。
- 准备测试运行环境:该技能反复强调"看到测试失败"“看到测试通过”,因此项目需要有可执行的测试命令(例如详情中出现的
npm test这类形式,具体以你项目的实际测试脚本为准)。没有可运行的测试命令,TDD 循环就无法闭环。
提示:安装命令、订阅方式、是否收费等信息,请以官方说明为准,本文不代为承诺。
2. 该技能的主要功能和特点
- 铁律约束机制:明确写入"没有生产代码,除非先有失败测试"。如果先写了实现代码,规则要求直接删除重写,不允许"保留作参考"、不允许"写测试时顺手调整它"、不允许"先看一眼再说"。删除就是删除。
- 完整的 Red-Green-Refactor 循环:技能内置了流程图式的四段式流程——RED 写失败测试 → 验证失败正确 → GREEN 写最小代码 → 验证全部通过 → REFACTOR 清理 → 进入下一个循环。
- 双重强制验证:不只是"写测试",还强制要求运行测试并亲自确认结果。测试必须因为"功能缺失"而失败,而不是因为拼写错误而报错;测试通过后必须确认其他测试依然绿色、输出纯净(无错误、无警告)。
- 最小实现原则(对抗过度设计):GREEN 阶段只写"刚好够通过"的代码。技能用正反示例说明:能用一个 for 循环解决的重试逻辑,就不要再加
maxRetries、backoff、onRetry这类没人要求的参数。 - 好测试的质量标准:以表格形式给出"最小、清晰、显示意图"三条标准,并提示"测试名称里出现’和’字就拆开",同时明确优先使用真实代码,除非不可避免,否则不使用模拟对象。
- 反合理化对照表:这是该技能最有辨识度的部分。它把开发者最常用的借口逐条列出并给出反驳,例如"太简单不用测"“我之后补测试”“我已经手动测过了”“删掉 X 小时的工作太浪费”(沉没成本谬误)“TDD 是教条主义,我是实用主义”。
- 红旗清单:列出十余条"必须停下来重来"的信号,比如代码先于测试、测试后于实现、测试一写就通过、无法解释测试为什么失败、说出"就这一次"等。
- 完成前的验证清单:用可勾选的清单收尾——每个新函数有测试、实现前看到每个测试失败、每个测试因预期原因失败、写了最小代码、所有测试通过、输出纯净、使用真实代码、覆盖边界与错误。勾不满就是跳过了 TDD,需要重来。
- 卡住时的应对指引:不知道怎么写测试?先写期望的 API 和断言。测试太复杂?说明设计太复杂。什么都得 mock?说明耦合太重,应改用依赖注入。
- 与调试流程打通:发现 bug 时先写一个能重现该 bug 的失败测试,再走 TDD 循环,让测试既证明修复有效,又防止回归。“从不修复没有测试的 bug”。
- 反模式联动:技能指明在添加模拟或测试工具时,需要阅读配套的测试反模式文档,避免"测试模拟对象的行为而非真实行为""为了测试给生产类加测试专用方法"等陷阱。
与普通的"帮我写测试"提示词相比,它的差异不在于能不能生成测试代码,而在于用流程和清单把"验证"变成了不可跳过的一环。
3. 如何使用该技能?
触发方式
技能会在以下场景自动介入:新功能开发、错误修复、重构、行为变更。详情中列出的例外情况(临时原型、生成代码、配置文件)需要与协作方确认后再决定,而不是自行跳过。
如果你在对话中直接提出实现需求,可以显式加上一句触发语,例如:
“用测试驱动开发的方式实现这个功能:操作失败时自动重试 3 次。”
分步操作指南
第 1 步:RED —— 写一个失败测试
只写一个行为、名称清晰、尽量使用真实代码。例如实现"失败操作重试 3 次":
test('重试失败操作3次', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('失败');
return '成功';
};
const result = await retryOperation(operation);
expect(result).toBe('成功');
expect(attempts).toBe(3);
});
反面写法是 test('重试有效') 配一堆 mockRejectedValueOnce —— 名称模糊,而且测的是模拟对象而非真实行为。
第 2 步:验证 RED —— 运行测试,亲眼看它失败
npm test path/to/test.test.ts
确认三件事:测试确实失败(而不是报错崩溃)、失败信息符合预期、失败原因是功能缺失而非拼写错误。
如果测试直接通过了,说明你测的是已经存在的行为,需要回去修改测试。
第 3 步:GREEN —— 写最小代码
只写让测试通过的最简实现:
async function retryOperation<T>(fn: () => Promise<T>): Promise<T> {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('不可达');
}
此时不要添加测试没要求的功能,不要顺手重构其他代码。
第 4 步:验证 GREEN —— 再次运行测试
确认测试通过、其他测试仍通过、输出无警告。如果测试失败,修复代码,而不是修改测试。
第 5 步:REFACTOR —— 在绿色状态下清理
删除重复、改进命名、提取辅助函数,全程保持测试绿色,不新增任何行为。
第 6 步:重复
下一个功能,从下一个失败测试开始。
错误修复的用法示例
缺陷:表单接受了空邮箱。
RED:写测试 test('拒绝空电子邮件'),断言返回 { error: '需要电子邮件' }。
验证 RED:运行后输出"预期 ‘需要电子邮件’,获得 undefined"——失败原因正是功能缺失。
GREEN:在 submitForm 里加上 if (!data.email?.trim()) return { error: '需要电子邮件' };。
验证 GREEN:测试通过。
REFACTOR:如果多个字段都需要校验,再提取校验助手。
输入与输出说明
- 输入:一句功能描述或一个 bug 描述,越具体越好(包含期望行为、边界条件)。
- 输出:一串按顺序产生的产物——失败测试用例 → 测试运行结果 → 最小实现代码 → 通过结果 → 重构后的代码 → 验证清单勾选情况。
4. 同类型竞品对比分析
| 方案名称 | 定位 | 核心功能 | 安装/使用门槛 | 适用场景 | 优势与不足 |
|---|---|---|---|---|---|
| 测试驱动开发Skill(本技能) | 方法论约束型技能,管住"顺序" | 强制 RED-GREEN-REFACTOR 闭环、双重运行验证、反合理化对照表、红旗与验证清单 | 需支持 Skill 机制的环境;需项目具备可运行的测试命令;安装方式以官方说明为准 | 新功能、缺陷修复、重构、行为变更 | 优势:从流程上杜绝"假测试",产出可信任;不足:对一次性的探索性脚本而言节奏偏慢,需要开发者配合执行测试命令 |
| 直接让 AI 写代码(无技能) | 通用编码助手默认模式 | 根据需求直接输出完整实现 | 零门槛 | 快速出原型、脚本、一次性任务 | 优势:速度最快;不足:几乎不产生有效验证,代码质量依赖人工复核,长期维护成本高 |
| 提示词"帮我补测试" | 事后补测 | 针对已有实现生成测试用例 | 低,一句话即可 | 给遗留代码补覆盖率 | 优势:见效快;不足:测试一写就通过,无法证明其有效性;容易测实现细节而非行为,边界覆盖靠"回忆" |
| 人工 TDD + 团队规范 | 传统工程实践 | 开发者手工执行红绿重构,靠 Code Review 把关 | 中高,依赖个人习惯与团队文化 | 成熟团队、核心业务模块 | 优势:最扎实;不足:执行成本高、容易在赶工期时被放弃,且缺少逐条清单式的强制校验 |
| CI 覆盖率门禁 / Lint 规则 | 流水线层质量闸门 | 用覆盖率阈值、静态检查拦截不合格提交 | 中,需要配置 CI | 团队级质量兜底 | 优势:自动化、不可绕过;不足:覆盖率是结果指标,无法保证测试"先失败过",高覆盖率低有效性很常见 |
选型建议:把本技能理解为"过程约束",把覆盖率门禁理解为"结果约束",两者互补。若你主要用 AI 生成代码且项目需长期维护,本技能的优先级应高于事后补测。
5. 该技能的典型应用场景与实际体验情况
场景一:后端工程师修复线上缺陷
- 角色与痛点:线上出现"空邮箱可提交"的校验漏洞。工程师急于修复,习惯先改代码再补测试,结果同类问题在别的表单反复出现。
- 使用方式:先用一个失败测试重现该漏洞,确认测试因"功能缺失"而失败,再写修复代码,最后跑全量测试。
- 实际体验:多花了大约写一个测试的时间,但换来了可复现的证明和永久防回归的护栏。注意事项:一定要确认失败信息是"预期值不符"而不是"函数未定义",否则你只是测出了语法错误。
场景二:全栈开发者用 AI 新增业务功能
- 角色与痛点:用 AI 快速生成功能代码,代码看起来能跑,但边界条件(空值、超时、并发)几乎没被覆盖,上线后问题集中爆发。
- 使用方式:在需求描述里明确要求按 TDD 流程推进,让 AI 先输出测试、等测试跑失败、再输出最小实现。
- 实际体验:AI 输出的第一版实现明显更"克制"——不会一上来就堆砌一堆没人用的可选参数。注意事项:技能会要求删除"先写后测"的代码,如果 AI 提出要删掉你已经写好的实现,请配合,这正是技能价值所在。
场景三:重构遗留模块
- 角色与痛点:一段没有测试的老代码需要重构,谁也不敢动,一改就怕出问题。
- 使用方式:先为现有行为补充测试(这一步属于"为现有代码添加测试"的改进行为),再进入红绿重构循环,每轮重构后保持全部测试绿色。
- 实际体验:重构从"凭感觉"变成"有安全网的小步移动"。注意事项:如果某个类极难写测试,技能会提示"难测试 = 难使用",这通常意味着接口设计需要先简化,而不是测试写得不够巧。
场景四:技术负责人做代码评审
- 角色与痛点:评审时很难判断提交里的测试是否真的有效,只能看覆盖率数字。
- 使用方式:用技能中的验证清单作为评审清单,逐条对照:每个新函数是否有测试?是否在实现前看到过失败?
- 实际体验:把主观的"感觉代码质量还行"变成了可勾选的客观项。注意事项:清单是过程证据,评审时仍需询问开发者测试失败的具体原因。
6. 该技能能为用户带来的价值
- 把"验证"变成不可跳过的动作:最大的价值不是让 AI 会写测试,而是让"看到测试失败"成为流程中的硬性关卡。一个从未失败过的测试,和一个没有测试的模块,在可信度上没有本质区别。
- 显著降低调试成本:技能的核心论点是"TDD 比调试更快"。缺陷在提交前被发现,成本远低于在生产环境定位;而每一个失败测试同时就是一份永久生效的回归防护。
- 降低 AI 协作的信任门槛:当 AI 生成的每一段实现都有对应的、先失败过的测试作为证据时,开发者从"逐行审查 AI 代码"变成"审查测试是否合理",认知负担大幅下降。
- 减少返工与沉没成本浪费:技能点明了"保留无法信任的代码才是真正的浪费"。删除重写看似损失几小时,实际是避免在不可信的代码上继续叠加工作量。
- 测试即文档:先写的测试回答的是"这段代码应该做什么",它记录的是需求意图而非实现细节,对新成员理解系统特别友好。
- 长期可量化的收益方向:回归缺陷数量下降、缺陷发现时间前移、重构信心提升。具体提升幅度因项目规模与团队执行力而异,需结合自身数据评估。
7. 常见问题 FAQ
Q1:这个技能怎么安装?需要付费吗?
在支持技能机制的 AI 编程助手环境中,通过技能市场或技能目录检索技能英文名 test-driven-development 或技能ID 11822 即可安装启用,具体入口、命令与收费方式以官方说明为准。安装本身不复杂,真正需要准备的是项目里可运行的测试命令。
Q2:它和直接对 AI 说"帮我写测试"有什么区别?
区别在于顺序和证据。事后补的测试一写就通过,无法证明它测对了东西;本技能强制你先看到测试失败,从而证明这个测试确实在测试功能缺失。技能原文的说法是:之后写的测试回答"这做什么",先写的测试回答"这应做什么"。
Q3:如果我已经写好了实现代码,AI 会怎么处理?
按照铁律,先有代码后有测试属于违规,技能要求删除实现代码,用 TDD 重新开始,并且明确禁止"保留作参考"“写测试时顺手调整它”。这看起来激进,但目的是避免你被已有实现带偏,只测"自己写了什么"而不是"需求要什么"。
Q4:小改动、简单代码也要走完整流程吗?
技能的态度是"简单代码也会坏,测试只要 30 秒",因此默认适用于新功能、缺陷修复、重构和行为变更。对于临时原型、生成代码、配置文件,详情中列为需要与协作方确认的例外情况,而不是让开发者自行跳过。
Q5:和覆盖率门禁、团队 TDD 规范怎么配合?
本技能管的是"过程是否合规",覆盖率门禁管的是"结果是否达标",团队规范管的是"人是否执行"。三者不冲突:技能保证每个测试都先失败过,覆盖率保证整体覆盖面积,CI 保证规则不被绕过。如果只能选一个,对于大量使用 AI 生成代码的团队,优先保证"过程"更有意义。