测试驱动开发Skill:先写一个会失败的测试,再写刚好能通过的最小代码
- 一句话定位:这不是一个测试框架,而是一套"行为约束"技能——它强制 AI 在写任何生产代码之前,先写测试、先看着测试失败,然后才允许写实现。
- 核心铁律:没有失败的测试之前,不写生产代码。如果先写了代码,答案是把代码删掉,从测试重新开始。
- 工作循环:红(写失败测试)→ 验证红(亲眼看着它因预期原因失败)→ 绿(写最小代码通过)→ 验证绿(全部通过、输出纯净)→ 重构(仅在绿灯后)。
- 最大差异点:它把"事后补测试"“我手动测过了”"太简单不用测"这类合理化借口逐条列出并逐条反驳,让 AI 无法用"实用主义"话术绕过纪律。
- 适用人群:需要让 AI 结对编程产出可信代码的后端/前端工程师、做遗留代码改造的团队、以及需要把 TDD 规范落到日常协作里的技术负责人。
1. 该技能叫什么?如何一键安装 AI 技能提升开发效率?
技能基本信息
| 项目 | 内容 |
|---|---|
| 中文名 | 测试驱动开发Skill |
| 英文名 | test-driven-development |
| 技能ID | 12116 |
| 触发时机 | 在实现任何功能或修复错误之前、在编写实现代码之前使用 |
它解决什么问题?
当你把需求丢给 AI 编程助手时,最常见的产出路径是:直接生成一大段实现代码 → 事后补几个测试 → 测试一跑全绿 → 看起来"完成"。问题在于:立即通过的测试什么也不能证明。它可能测错了对象,可能测的是实现细节而非行为,可能漏掉了你压根没想到的边界情况,而且你从未亲眼看见它抓到过一次错误。这个技能的作用,就是把这条"看起来很快"的路径堵死,把 AI 拉回"先写测试、看着它失败、再写最小实现"的轨道上。
一键安装的思路与步骤
- 确认前提:你的 AI 编程助手/Agent 平台需要支持 Skill(技能)机制,能够加载外部技能说明作为行为约束。具体支持范围与版本要求以官方说明为准。
- 找到入口:在平台的技能市场、技能目录或插件管理页中搜索技能英文名
test-driven-development或技能中文名"测试驱动开发Skill";部分平台也支持通过技能ID12116精确检索。具体搜索入口与安装命令以官方说明为准。 - 执行安装/启用:按平台提示完成安装并启用该技能,使其在会话中可被调用或自动生效。
- 在会话中显式引用:开始一个开发任务前,明确告诉助手"使用测试驱动开发Skill",或在平台的技能选择器中勾选它。
- 验证是否生效:给它一个极小的需求(例如"实现一个函数:邮箱为空时返回错误’邮箱必填’"),观察输出顺序。生效的标志是:它第一步先给出一个失败的测试用例,并说明预期的失败信息;而不是直接甩出实现代码。如果它直接写了实现,说明技能没有被正确加载。
2. 该技能的主要功能和特点
- 铁律级前置约束:明确规定"没有失败的测试前不写生产代码"。已经先写了代码?答案是删除重写——不保留为"参考"、不"适配"它去补测试、不看它,从测试开始重新实现。
- 红-绿-重构闭环:把开发拆成"写失败测试 → 验证失败 → 写最小代码 → 验证通过 → 重构 → 下一个",每一步都带验证关卡。红阶段验证失败原因是否正确(是功能缺失,而不是拼写错误);绿阶段验证是否全部测试通过且输出纯净(无错误、无警告)。
- 强制"看着它失败":这是技能反复强调的核心原则——如果你没看着测试失败,你就不知道它测试的是否正确。测试一上来就通过?说明你在测试已有行为,要改测试。
- 最小实现与反过度工程:绿阶段只写刚好能通过测试的代码。示例中,一个"重试失败操作 3 次"的测试,正确实现是几行的简单循环;而带
maxRetries、backoff、onRetry参数的"通用重试框架"被明确标为过度工程(YAGNI)。 - 好测试的质量标尺:一个好测试必须"最小、清晰、显示意图"——一个测试只测一件事(测试名里出现"和"就该拆开)、名称描述行为而不是
test('测试1')、以及演示期望的 API 用法。并且要求尽量使用真实代码,除非不可避免否则不用模拟。 - 合理化拦截清单:把工程师最常用的 11 条借口做成对照表,逐条反驳。例如"太简单了不用测"→ 简单代码也会坏,测试只要 30 秒;“我之后补测试”→ 事后测试立即通过,证明不了任何东西;“删除 X 小时工作是浪费”→ 沉没成本谬误,真正浪费的是保留你不信任的代码;“TDD 是教条的,我在实用”→ TDD 恰恰是实用的,提交前找 bug 快于上线后再调试。
- 红旗熔断机制:一旦出现"代码先于测试"“测试立即通过”“我手动测过了”"仅此一次"等信号,技能要求立刻停下并重新开始,而不是继续往前推。
- 完成前验证清单:每个函数都有测试、每个测试都在实现前被看着失败、每个测试因预期原因失败、写的是最小代码、全部通过、输出纯净、真实代码优先、边界与错误覆盖——任一项无法勾选,就等于跳过了 TDD,需要重做。
- 卡住时的排障指引:不知道怎么写测试 → 先写愿望 API 和断言;测试太复杂 → 说明设计太复杂,简化接口;必须模拟一切 → 代码太耦合,改用依赖注入;测试前置设置巨大 → 提取助手,仍然复杂则简化设计。
- 调试集成:发现 bug 时,先写一个能重现它的失败测试,再走 TDD 循环。测试同时证明修复有效并防止回归——“没有测试,从不修复错误”。
- 反模式联动:在引入模拟或测试工具时,技能会提示阅读测试反模式文档,避免"测试了模拟行为而非真实行为"“给生产类加仅测试用的方法”"不理解依赖就乱模拟"等常见坑。
和普通工具比强在哪? Jest、Vitest、pytest 这些是"测什么都能跑"的执行器,它们不关心你什么时候写测试;通用 AI 代码助手天然倾向于"先给能跑的代码"。这个技能补的正是中间那层——流程纪律。它不提供新的断言能力,而是让 AI 在正确的时间做正确的事,并把"跳过"的行为识别为需要纠正的偏差。
3. 如何使用该技能?
以下是典型的分步使用方式,适用于支持该技能加载的 AI 编程助手会话。
步骤 1:加载技能并声明任务
在会话开头明确声明使用该技能,并给出一个小而具体的行为需求。例如:
使用测试驱动开发Skill,为表单提交实现邮箱校验:邮箱为空时返回错误"邮箱必填"。
步骤 2:让 AI 先产出"红"(失败测试)
期望输出是一个最小、名称清晰的测试,只测一个行为。示例:
test('拒绝空邮箱', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('邮箱必填');
});
步骤 3:运行测试并确认它失败
由 AI 或你自己执行测试(技能示例中使用 npm test 加上目标测试文件路径),确认三点:它确实是失败(而不是报错)、失败信息是预期的、失败原因是功能缺失而不是打字错误。典型输出形如:
失败: 期望 ‘邮箱必填’, 得到 undefined
步骤 4:让 AI 写"绿"(最小实现)
只写刚好让测试通过的最简单代码,不加任何测试未要求的能力:
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: '邮箱必填' };
}
// ...
}
步骤 5:再次运行,确认通过且输出纯净
确认本测试通过、其他测试仍然通过、没有额外错误或警告。此时若失败,修的是代码,不是测试。
步骤 6:可选重构,然后进入下一个循环
只有在绿灯之后才允许重构:移除重复、改进命名、提取助手函数,且必须保持测试绿色、不新增行为。然后为下一个行为写下一个失败测试。
输入示例(新功能):想要"重试失败操作 3 次",就给出测试期望的行为——第一次和第二次抛错、第三次成功,最终结果为"成功"且尝试次数为 3。输出说明:技能会要求先给出这个测试、运行看到失败,再给出一个简单的三次循环实现,而不是一上来就交出带退避策略和回调的通用重试工具。
4. 同类型竞品对比分析
| 方案名称 | 定位 | 核心功能 | 安装/使用门槛 | 适用场景 | 优势与不足 |
|---|---|---|---|---|---|
| 测试驱动开发Skill(本技能) | 面向 AI 编程过程的 TDD 纪律约束 | 铁律前置、红-绿-重构闭环、合理化拦截、红旗熔断、完成前验证清单 | 需在支持 Skill 机制的助手中安装启用,门槛低;但需要使用者愿意遵守流程 | 让 AI 结对开发新功能、修 bug、重构遗留代码 | 优势:把"先写测试"变成无法绕开的行为,测试可信度高;不足:不提供测试执行能力,依赖已有测试框架,且对一次性原型等场景需人工判断例外 |
| 通用 AI 代码助手(直接生成实现) | 快速产出可运行代码 | 生成实现、补写部分测试 | 门槛最低,开箱即用 | 原型验证、脚手架、样板代码 | 优势:速度最快;不足:通常先写实现后补测试,事后测试立即通过,无法证明测试有效,回归风险高 |
| 单一测试框架(如 Jest、Vitest、pytest) | 测试执行与断言引擎 | 断言、模拟、覆盖率、并发执行 | 需自行配置工程与脚本,中等门槛 | 各类项目的自动化测试基础设施 | 优势:生态成熟、能力完整;不足:只负责"跑测试",不约束"何时写测试",纪律完全依赖人 |
| 行为驱动开发(BDD,如 Cucumber、SpecFlow) | 用自然语言描述可执行的行为规格 | Given-When-Then 场景、业务可读的验收测试 | 需要额外的特性文件与步骤定义,门槛较高 | 跨角色协作、验收测试、需求可追溯 | 优势:业务方能读懂,沟通价值高;不足:层层封装后维护成本高,单元级快速反馈不如 TDD 循环,且同样不解决"先写还是后写"的问题 |
怎么选? 如果你已经有一套测试框架,缺的只是"什么时候写测试"的纪律,本技能是最直接的补位;如果你需要业务方参与验收,BDD 更合适;如果只是临时验证想法,直接让助手生成实现反而更划算——但要清楚那不属于 TDD 流程。
5. 该技能的典型应用场景与实际体验情况
场景一:后端工程师修线上 bug
角色:负责表单/接口校验的后端工程师。痛点:线上出现"接受空邮箱"的缺陷,匆忙改一行 if 就上线,下次改动又把校验弄丢了。使用方式:先用技能写一个重现缺陷的失败测试(期望返回"邮箱必填",实际得到 undefined),看着它失败,再写最小修复,最后看着它通过。实际体验:这类小修复通常一两分钟就能走完一个循环,最大的收获不是那一行代码,而是从此以后这条回归路径被自动守住了。注意:如果测试第一次就通过,说明你写的测试没测到缺陷,必须回头改测试。
场景二:AI 结对编程时的行为纠偏
角色:习惯用 AI 生成代码的开发者。痛点:AI 生成的代码"看起来能跑",但测试是事后补的,全绿也不安心,review 时无从判断逻辑边界是否覆盖。使用方式:在会话开头显式加载本技能并声明任务,把"先失败后通过"作为验收条件。实际体验:上手几乎零成本,因为不需要学新语法;真正的变化是输出顺序被固定住了——你会先看到测试、看到失败信息、再看到实现。注意:模型偶尔会用"这太简单了,直接写实现"这类话术尝试绕开,此时引用技能里的合理化对照表即可把它拉回来。
场景三:遗留代码改造与重构
角色:接手无测试老项目的开发者。痛点:不敢动代码,改一处崩三处,重构等于赌博。使用方式:借助技能的"卡住时"指引——不知道如何测试就先写愿望 API 和断言;测试前置设置太大就提取助手,仍复杂则简化设计。为现有代码补测试,再在绿灯保护下重构。实际体验:前期投入明显高于直接改代码,但一旦测试网织起来,后续每次改动都有即时反馈。注意:技能明确提醒"现有代码没有测试"不是跳过 TDD 的理由,而是在改进它——为现有代码添加测试本身就是正当任务。
场景四:团队规范落地与代码评审
角色:技术负责人、评审者。痛点:TDD 写进规范容易,落地难,评审时无法判断测试是不是事后补的。使用方式:把技能中的"完成前验证清单"和"红旗清单"直接作为 PR 自查项与评审依据。实际体验:清单把模糊的"要有测试"变成可勾选的具体条件,评审沟通成本明显下降。注意:技能也明确了例外情况——一次性原型、生成的代码、配置文件属于例外,但需要先与人类合作者确认,而不是自行决定跳过。
整体上手难度与注意事项:技能本身不需要额外学习成本,难点在于执行纪律。实际使用中要留意三点:一是测试运行速度要快,否则高频的"验证红/验证绿"会拖慢节奏;二是警惕模拟滥用,技能要求优先使用真实代码,测试了模拟行为等于什么都没测;三是不要把流程做成形式主义——走了两个循环却没真正看过失败原因,等于没做。
6. 该技能能为用户带来的价值
- 把"测试可信"变成默认结果:最大的价值不在于测试数量变多,而在于每个测试都曾经红过一次——你知道它确实能抓到东西。事后补的测试只回答"这代码做了什么",测试先行的测试回答"这代码应该做什么",后者的边界往往是在写断言时才被发现出来的。
- 把缺陷拦截点前移到提交之前:技能本身给出了明确的效率论据——在提交前找到错误快于之后调试,测试立即捕获中断而防止回归,测试本身就是"如何使用这段代码"的活文档,并且让重构从"赌博"变成"自由变更,测试兜底"。
- 降低 AI 协作的信任成本:AI 生成代码的通病是"看不出来哪里不对"。有了先失败后通过的证据链,review 从"读一大段实现猜逻辑"变成"看测试断言是否符合预期",审查负担显著下降。
- 降低团队门槛:新手最缺的不是写代码能力,而是"先想清楚要什么行为"的习惯。技能的验证清单和排障表把抽象方法论拆成了可执行动作,也顺带给出了设计反馈——测试难写往往意味着接口难用,这是免费的设计评审。
- 长期价值:留下的不是一次性通过的绿灯,而是一张随代码演进持续运行的回归网。技能里那句"浪费"的重新定义值得记住——真正浪费的是保留你不信任的代码;没有真实测试的工作代码是技术债务。
7. 常见问题 FAQ
Q1:这个技能怎么安装?收费吗?
A:在支持 Skill 机制的 AI 编程助手或 Agent 平台中,通过技能市场/技能目录搜索英文名 test-driven-development、中文名"测试驱动开发Skill",或用技能ID 12116 检索后安装启用。具体安装入口、命令与是否收费取决于所在平台,以官方说明为准。安装后建议用一个极小需求验证:看它是否先给你失败测试而不是实现代码。
Q2:它和直接写单元测试有什么区别?我不是已经在写测试了吗?
A:区别在顺序,而顺序决定证据强度。写后测试会立即通过,立即通过无法证明它测对了对象、测的是行为而非实现、覆盖了你忘记的边界。这个技能要求你先看着它失败,失败原因必须是"功能缺失"而不是"打字错误"。如果你从来没在实现前看过一次红色,那你做的是测试,不是测试驱动开发。
Q3:TDD 会不会明显拖慢开发速度?
A:技能的立场是:TDD 快于调试,所谓"实用"的捷径往往等于在生产环境里调试,那更慢。真实感受是——单个功能确实多出"跑一次失败"和"跑一次通过"两趟,但省下的是上线后定位问题、以及每次改动都要手动重测所有边界的时间。手动测试是临时的、无记录的、无法在代码变更后重跑的,自动化测试每次都以同样方式运行。
Q4:什么情况下可以不用?
A:技能列出的例外只有三类:一次性原型、生成的代码、配置文件——并且要求先向人类合作者确认,而不是自己拍板。至于"这次的 bug 太简单""我先探索一下"这类理由,都明确属于需要被拦截的合理化:探索可以,但探索完要抛弃探索代码,从测试重新开始。
Q5:适合谁用?和竞品怎么选?
A:最适合正在用 AI 结对写代码、又希望产出可被信任的工程师,以及需要把 TDD 规范真正落地的团队。选择逻辑是:已有测试框架、只缺纪律约束 → 选本技能;需要业务方参与验收、强调可读规格 → 考虑 BDD 方案;只是临时验证想法 → 直接生成实现更划算,但要清楚那不是 TDD。本技能不替代 Jest、Vitest、pytest 等执行器,它是叠加在它们之上的流程层。