技能使用指南

test-driven-development(测试驱动开发)Skill 是什么?为什么必须先看测试失败?

test-driven-development(测试驱动开发)Skill 用一条铁律约束 AI 编码助手:没有先失败的测试,就不该存在生产代码。本文讲清红-绿-重构循环、强制验证失败的判断标准、常见借口对照表与完工验证清单,对比普通 AI 编码、传统 TDD 规范文档与覆盖率工具的差异,并给出缺陷修复、重构、结对编程的真实体验与安装验证方法,帮你几分钟内把这个技能用起来。

测试驱动开发Skilltest-driven-development
8 个章节 约 14 分钟阅读 AI 智能生成

测试驱动开发:先写一个会失败的测试,再写刚好能通过的代码

  • 一条铁律:没有先观察到失败的测试,就不允许存在生产代码;如果先写了代码,正确做法是删掉重来,而不是"留着当参考"。
  • 三步闭环:红(写失败测试)→ 绿(写最小实现)→ 重构(保持全部通过),每一步都必须亲眼验证运行结果。
  • 反"假绿"设计:技能反复强调"测试一写就通过,说明你在测试已有行为",从机制上堵住 AI 助手最爱走的捷径。
  • 可执行的纪律:内置借口对照表、红色信号清单、完工验证清单和卡住对策表,把抽象的"要写测试"变成逐条打勾的检查表。
  • 覆盖全流程:新功能、缺陷修复、重构、行为变更默认全部适用,一次性原型、生成代码、配置文件属于例外,需征求人类伙伴同意。

1. 该技能叫什么?如何一键安装 AI 技能提升开发效率?

技能中文名:测试驱动开发 技能英文名:test-driven-development 技能 ID:13645

它要解决的是一个非常具体的工程问题:AI 编码助手写代码太快了,但它的"测试"往往不可信。典型症状是先一口气写完实现,再补一堆测试;跑起来全绿,你以为验证过了,实际上测试只是把实现又描述了一遍——错误逻辑被原样复制进测试里,谁也没抓到 bug。

这个技能不给你的项目添加任何依赖库,它约束的是写代码的顺序:先写一个表达"应该发生什么"的测试,运行它、亲眼看到它失败、确认失败原因是功能缺失而不是拼写错误,然后才允许写实现,且实现必须"最小"。这个顺序一旦被颠倒,测试的证明力就归零了。

关于"一键安装",按通用流程操作即可:

  1. 确认前提:你所使用的 AI 客户端或 IDE 插件需要支持"技能/插件"这类可挂载的能力扩展;若客户端不支持技能机制,则只能把技能内容作为提示词规则手动引入。
  2. 找到入口:在客户端的技能市场、技能列表或本地技能目录中,使用技能英文名 test-driven-development 或技能 ID 13645 进行搜索/定位。
  3. 一键安装/启用:通过市场安装按钮或导入技能文件完成挂载,安装后在技能列表中应能看到"测试驱动开发"这一条目处于已启用状态。
  4. 验证是否生效:新开一个会话,让它"用 TDD 的方式实现一个小功能",观察它的第一动作是不是先产出测试文件并执行测试命令、然后汇报失败信息。如果它上来就写实现代码,说明技能没有被正确加载或没有被触发。

具体的安装命令、技能目录路径、是否需要账号或付费等细节,技能详情中并未提供,请以官方说明为准,不要臆造命令。

2. 该技能的主要功能和特点

  • 铁律约束(Hard Rule):技能明确写出"没有先有失败测试的生产代码"。在测试之前写了代码?删掉,重新开始。而且明确堵住了几个常见退路:不要保留它当"参考"、不要写测试时"适配"它、甚至不要看它——删除意味着删除。
  • 红-绿-重构闭环:技能用流程图定义了完整循环——写失败测试 → 验证失败是否正确 → 写最小代码 → 验证全部变绿 → 在绿色状态下重构 → 进入下一个测试。任何一步验证不通过都要回到上一步,而不是往前走。
  • 强制"观察失败":这是整个技能的核心论断——“如果你没有观察测试失败,你就不知道它测试的是正确的事情”。技能要求失败必须是断言失败而非运行报错,失败信息必须是预期的,失败原因必须是功能缺失而不是拼写错误。测试如果直接通过,说明你在测试已有行为,必须修测试。
  • 最小实现(YAGNI):绿灯阶段只允许写"刚好能通过"的代码,禁止顺手加参数、加退避策略、加回调扩展。技能直接给出了"过度工程"的反例写法作为警示。
  • 重构有前置条件:只有全部测试变绿之后才允许重构,且重构不得添加任何新行为;重构完必须再次确认测试仍然全绿。
  • 好测试的判据表:从"最小(一件事,名字里有’和’就拆开)"“清晰(名字描述行为)”"显示意图(演示期望的 API)“三个维度给出好坏对照,并明确"真实代码优先,除非不可避免不使用模拟”。
  • 反理性化工具箱:技能列出了 11 条开发者最常说的借口(“太简单无需测试”“我稍后补测试”“我已经手动测过了”“删掉 X 小时工作太浪费”“TDD 太教条,我是务实的”)并逐条给出反驳,还单列了"红色信号清单"——一旦出现这些信号,动作只有一个:删代码,重新用 TDD 开始。
  • 完工验证清单:8 条勾选项,包括每个新函数都有测试、每个测试在实现前都被观察过失败、输出无警告等,勾不满就等于跳过了 TDD。
  • 卡住时的对策表:不知道怎么写测试就先写期望的 API 和断言;测试太复杂说明设计太复杂;什么都得模拟说明耦合太紧要用依赖注入。
  • 调试集成:发现 bug 时,先写一个能复现它的失败测试,再走 TDD 循环,让测试既证明修复有效,又防止回归——“没有测试永不修复错误”。

和普通 AI 编码助手的差别在于:普通助手把测试当成"交付物的一部分",本技能把测试当成证明手段,并且用顺序和验证动作保证这个证明是真的。

3. 如何使用该技能?

步骤 1:触发技能并明确行为 在会话中直接说明使用 TDD,并描述你想要的行为(而不是描述实现)。例如:

用测试驱动开发的方式,为 submitForm 增加邮箱校验:空邮箱应返回错误提示"需要电子邮件"。

步骤 2:红——先写失败测试 技能会引导产出最小、名字清晰的测试。参考详情中的写法:

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);
});

注意这个测试"测试真实行为"而非测试模拟调用次数——详情里专门给了反例:用 jest.fn() 链式 mock 再断言 toHaveBeenCalledTimes(3),属于"测试模拟而非代码",名字也模糊。

步骤 3:验证红——运行并观察失败 执行测试命令(详情示例为 npm test 路径/到/test.test.ts),然后逐项确认:是断言失败而不是语法/导入错误、失败消息符合预期、失败原因是功能尚未实现。若测试直接通过 → 修测试;若测试报错 → 修错误,重跑到"正确地失败"。

步骤 4:绿——写最小实现 只写足以通过的那几行。详情给出的正例是一个三行循环:

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('不可达');
}

而反例是同时引入 maxRetries、backoff、onRetry 等一堆用不上的配置项——那不是 TDD,那是提前设计。

步骤 5:验证绿——再次运行 确认三点:新测试通过、其他测试仍然通过、输出干净(无错误无警告)。测试失败 → 改代码不是改测试;其他测试挂了 → 立刻修。

步骤 6:重构 在绿色状态下移除重复、改进命名、抽取辅助函数,不加任何行为,改完再跑一遍确认仍然全绿。

步骤 7:重复 为下一个行为写下一个失败测试。每轮只推进一个行为,测试名里出现"和"就说明该拆成两个。

4. 同类型竞品对比分析

方案名称 定位 核心功能 安装/使用门槛 适用场景 优势与不足
测试驱动开发(本技能) 约束 AI 编码顺序的行为规范型技能 铁律、红-绿-重构闭环、强制观察失败、最小实现、借口对照表、验证清单 需支持技能的客户端,一键挂载;无需改项目依赖 新功能、缺陷修复、重构、行为变更 优势:直接管住"先写实现再补测试"这个高频问题,规则可逐条核对;不足:会明显拉长单轮对话,对纯探索性原型偏重
普通 AI 编码助手(无技能约束) 通用代码生成 直接产出实现代码,测试多为事后补充 开箱即用 快速原型、脚本、一次性任务 优势:出活快;不足:测试常常"一写就绿",无法证明有效,容易把错误逻辑复制进测试
团队 TDD 规范文档 / 培训 人与流程层面的规范 书面约定、代码评审要求 需要培训与评审执行成本 团队统一工程文化 优势:覆盖面广;不足:靠人自觉,AI 不会自动遵守,落地衰减快
代码覆盖率工具 度量工具 统计行/分支覆盖率 需接入构建流程 质量看板、门禁 优势:可量化;不足:覆盖率 100% 也不代表测试有效,无法识别"写完实现再补测试"

一句话总结:覆盖率工具告诉你"测了多少",本技能保证"测试真的能失败"。

5. 该技能的典型应用场景与实际体验情况

场景一:后端工程师修复线上缺陷(空邮箱被接受) 痛点:修 bug 时最容易"先改一行再补测试",补出来的测试永远不会失败。使用方式:先写 test('拒绝空电子邮件') 并运行,看到 预期 '需要电子邮件', 得到 undefined,再写 if (!data.email?.trim()) 拦截。实际体验:流程更慢,但修复有据可查,回归测试自动覆盖;注意别在红色阶段顺手改别的逻辑。

场景二:AI 结对编程时防止"假绿测试" 痛点:AI 助手生成的测试经常直接通过,你无法判断它验证了什么。使用方式:要求它先跑测试并贴出失败输出,再写实现。实际体验:这是本技能收益最明显的地方——它会主动拒绝"测试通过了,看起来没问题"这类汇报;注意事项是要给它可执行的测试命令,否则无法进入验证环节。

场景三:重构没有测试覆盖的遗留代码 痛点:不敢动老代码,一改就怕炸。使用方式:为现有行为补测试(这是技能允许的"改进现有代码"路径),再在绿色状态下重构。实际体验:重构自由度显著提升;注意"为现有代码补测试"仍要求先看到失败,否则仍属于事后测试,需明确区分。

场景四:新人代码评审的统一标尺 痛点:评审时"测试写得好不好"全凭感觉。使用方式:用技能的验证清单和好测试判据表逐条过。实际体验:争议变少了,因为标准是客观的(一行为一测试、名字描述行为、无多余 mock);注意团队要先对齐"例外情况"的边界。

整体上手难度:低到中等。规则读一遍就能懂,难的是守住"删掉已经写好的代码"这一条。效果上,最大的变化不是测试变多,而是测试开始真的会红。注意事项:务必保证测试命令可运行、失败输出可观察;对于一次性原型、生成代码、配置文件,技能本身也承认可以例外,但要先和人类伙伴确认。

6. 该技能能为用户带来的价值

  • 把"验证"变成事实而非承诺:先失败后通过,是你唯一能确认"这个测试测对了东西"的手段。技能把这句话变成了强制动作。
  • 缺陷更早暴露,调试时间下降:技能明确指出,提交前发现错误比事后调试更快,回归测试会立刻捕获中断。
  • 重构敢下手:有测试兜底才敢改结构,长期看是代码可维护性的主要来源。
  • AI 输出质量可控:从"AI 写完我抽查"变成"AI 必须先证明测试有效",人工复核成本大幅下降。
  • 降低团队门槛:借口对照表 + 红色信号清单 + 验证清单,让不熟悉 TDD 的成员也能照着做,减少"这次先跳过"的灰色空间。
  • 长期价值:减少技术债。技能对"删除 X 小时工作很浪费"的回答是沉没成本谬误——真正浪费的是保留一份你无法信任的代码。

7. 常见问题 FAQ

Q1:这个技能怎么安装?需要付费吗? 在支持技能的 AI 客户端中,用英文名 test-driven-development 或技能 ID 13645 搜索并一键启用即可;验证方式是让它做一个 TDD 小任务,看它是否先写测试并汇报失败。具体安装入口、命令与是否收费请以官方说明为准。

Q2:先写代码再补测试,真的差那么多吗? 差的是证明力。事后写的测试一上来就是绿的,它回答的是"这段代码做了什么";先写的测试回答的是"这段代码应该做什么"。前者会被实现带偏,你想不到、记不全的边缘情况就被跳过了。技能的说法是:30 分钟后写测试不等于 TDD,你获得了覆盖率,但失去了证明。

Q3:适合谁用? 适合所有用 AI 写生产代码的人:后端/前端工程师、独立开发者、需要保证质量的团队,以及正在学习如何写测试的开发者。如果你只做一次性原型,技能本身也把它列为可豁免场景,但建议先确认。

Q4:为什么它坚持要删掉已经写好的代码?太浪费了吧? 技能给的逻辑是沉没成本:时间已经花掉了,你现在只能选"删掉用 TDD 重写(更多时间,高置信度)“或"保留再补测试(省 30 分钟,低置信度)”。而且它明确禁止"留着当参考"——因为你写测试时会不自觉地去适配它,那就变回了事后测试。

Q5:和代码覆盖率工具、团队 TDD 规范应该怎么选? 不冲突,是不同层。覆盖率工具负责告诉你"哪里没测到",团队规范负责人与人之间的约定,本技能负责约束 AI 与你在这一次编码过程中的动作顺序。三者叠加最稳:技能管顺序,覆盖率管盲区,规范管长期一致性。