
先说结论
这篇我想把 TDD、BDD、SDD 放到 AI 编程这件事里一次讲清楚。AI 编程这两年越来越火,很多人已经习惯了直接对 AI 说一句“帮我实现这个功能”,然后等它生成代码。这种方式很爽,也很快,但问题也很明显:代码看起来完成了,实际上可能没有真正跑通;页面看起来像那么回事,真实数据一接入就崩;按钮摆在那里,点了却没有完整逻辑;前端状态看起来很专业,背后却是假数据、假进度、假完成。
这就是很多人说的 Vibe Coding 的典型问题:靠感觉写代码,靠感觉验收结果。我的理解是,在 AI 编程时代,真正能把“想法”稳定变成“可交付产品”的,不是更长的 Prompt,而是一套更严谨的开发工作流。这套工作流里,有三个越来越重要的关键词:TDD、BDD、SDD。
如果只让我给一个实践结论,我会这样选:上游用 SDD 锚定意图,中间用 BDD 锚定可观察行为,下游用 TDD 锁实现质量。TDD 解决的是:代码有没有写稳;BDD 解决的是:功能行为是不是符合用户预期;SDD 解决的是:AI 到底有没有按照同一份规格去实现。换句话说,TDD 管代码正确性,BDD 管业务行为正确性,SDD 管产品意图正确性。
这也是为什么我现在更愿意把它们看成一条链,而不是三个互相竞争的概念:SDD 定义方向,BDD 定义行为,TDD 保证实现。没有 SDD,AI 可能不知道该盖什么房子;没有 BDD,房子可能结构合格但不好用;没有 TDD,细节质量可能随时塌。
为什么我想重新讲一遍 TDD、BDD、SDD
我之所以想把这个题目写透,不是因为 TDD、BDD 本身“新”,而是因为 AI 让它们在同一个项目里重新产生了关系。传统的 AI 编码工作流通常从一句“帮我写一个做 X 的功能”开始,随后进入“加功能、修 bug、补边界”的循环。但上下文越来越长之后,AI 代理会开始遗忘设计决策、误解目标,甚至给出与早先约束相矛盾的方案。
另一个重要背景是:AI 把“看似可用”和“真实可维护”之间的差距放大了。Cucumber 官方文档强调,BDD 关注的是 discovery、collaboration 和 examples,而不只是“测试”;GitHub 的 spec-driven.md 则更进一步提出,规格不应服务于代码,而应由代码服务于规格,验收场景也可以变成测试。我认为,这正是为什么 SDD 会在 AI 编程里迅速升温:它不是在争夺 TDD/BDD 的地盘,而是在为 AI 时代补上“规格缺位”这块最大的短板。
整理这篇时,我主要看了三类资料。第一类是官方或原始文档:GitHub Spec Kit 仓库、模板与 README,obra/superpowers 仓库与 skills/*/SKILL.md,Cucumber/Gherkin 官方文档,Aider 官方文档,OpenSpec 官方文档。第二类是官方或公司实践文章:GitHub Blog 关于 Spec Kit 与 GitHub Brain 的文章、微软 Learn 中文课程、KDDI 的企业 SDD 实践文章。第三类是近两年的行业观点,例如 Martin Fowler 对 AI + TDD 的观察。
TDD 是什么:先写测试,再写实现
TDD 的全称是 Test-Driven Development,中文通常叫测试驱动开发。它的核心思想很简单:不要先写功能代码,而是先写测试。一个经典 TDD 流程是:
- Red:先写一个失败的测试;
- Green:写最少的代码让测试通过;
- Refactor:在测试保持通过的前提下重构代码。
听起来有点反直觉。很多开发者第一反应是:功能都没写,怎么写测试?但这正是 TDD 的价值所在。当你先写测试时,你必须先想清楚:这个函数应该接收什么输入?应该返回什么结果?遇到异常情况应该怎么处理?边界条件是什么?什么才算“完成”?
比如你要写一个价格计算函数:
calculateFinalPrice({
price: 100,
discount: 0.2,
coupon: 10
})
你不能一上来就让 AI 随便写。你应该先定义测试:原价 100,八折后再减 10,最终应该是 70;折扣不能小于 0;优惠券不能大于折后价格;输入为空时要抛出明确错误。这时候测试就变成了开发边界。AI 可以自由实现,但不能突破测试定义的规则。
TDD 最适合解决什么问题
TDD 特别适合工具函数、算法逻辑、价格计算、权限判断、表单校验、接口数据转换、WordPress 插件里的业务逻辑、前端状态管理、后端服务方法。它的优势非常具体:减少回归问题;倒逼你拆小功能;让代码更容易重构;让 AI 不能只写“看起来合理”的代码;让验收从“我觉得可以”变成“测试确实通过”。
但 TDD 也有局限。TDD 更关注代码层面的正确性。它能证明一个函数、一个模块、一个接口在测试范围内是正确的,但它不一定能证明整个功能是否符合真实用户场景。比如所有单元测试都通过了,但用户点击购买按钮后,页面提示文案不对,订单状态显示混乱,支付失败后没有恢复按钮,这些问题未必能被传统 TDD 捕捉到。这时候就需要 BDD。
BDD 是什么:用业务语言描述行为
BDD 的全称是 Behavior-Driven Development,中文通常叫行为驱动开发。它不是简单地“写更多测试”,而是用用户、产品、业务都能理解的语言来描述系统行为。BDD 最常见的格式是:
- Given:给定某个前置条件;
- When:当用户执行某个动作;
- Then:系统应该产生某个结果。
例如:
Feature: 文章可见性控制
Scenario: 未登录用户访问隐藏文章
Given 一篇文章被设置为“仅登录用户可见”
And 当前访客没有登录
When 访客打开这篇文章详情页
Then 系统应该显示登录提示
And 不应该展示文章正文内容
这段内容不是单纯给程序员看的,它也是产品说明、测试用例、验收标准。BDD 的关键价值在于:它让“需求”变成了可讨论、可验证、可执行的行为描述。
BDD 最适合解决什么问题
BDD 很适合处理完整用户流程,例如登录注册流程、会员购买流程、文章权限控制、后台设置保存、采集源配置预览、文件上传与失败重试、前端 UI 交互、多角色权限差异、支付、订单、下载、授权等业务闭环。
BDD 特别适合前端工程师和产品型开发者,因为前端最容易出现“看起来做了,实际上没完成”的问题。比如一个后台设置页:按钮有了,但没保存;提示有了,但不是根据真实结果显示;进度条有了,但只是定时器假进度;预览区有了,但展示的是假数据;错误状态有了,但真实接口失败时没有触发。这些问题用普通单元测试很难覆盖,但用 BDD 场景就很容易暴露:
Given 采集源字段映射配置为空
When 用户点击实时预览
Then 系统应该显示明确的缺失字段提示
And 不应该展示伪造的成功预览结果
这就是 BDD 对 AI 编程特别重要的原因:它可以防止 AI 做出“表面完成”的 UI。
SDD 是什么:把规格变成开发的源头
SDD 的全称是 Spec-Driven Development,中文可以叫规格驱动开发或规范驱动开发。它和 TDD、BDD 最大的区别在于:SDD 不是从测试开始,也不是从行为场景开始,而是从规格开始。
规格不是一句模糊需求,例如“帮我做一个文章隐藏功能”。更好的规格应该是一份开发契约:这个功能解决什么问题;哪些用户会用;有哪些核心场景;哪些行为必须支持;哪些边界不能突破;哪些数据是真实的;哪些 UI 状态不能伪造;哪些性能、安全、兼容性要求必须满足;如何验收;哪些内容不在本次范围内。
在 AI 编程时代,SDD 的意义变得非常突出。因为 AI 很擅长写代码,但它并不总是知道你真正想要什么。如果规格不清楚,AI 就会根据自己的常见模式去猜。猜对了,你觉得它很智能;猜错了,它也可能写出一堆看起来很专业的代码。SDD 要解决的正是这个问题:先定义“要做什么”和“做到什么程度”,再让 AI 去实现。
TDD、BDD、SDD 的区别
可以用一句话区分三者:
- TDD:从测试驱动代码。
- BDD:从行为驱动验收。
- SDD:从规格驱动整个开发过程。
| 方法 | 关注重点 | 主要产物 | 适合对象 | 最适合解决的问题 |
|---|---|---|---|---|
| TDD | 代码是否正确 | 单元测试、集成测试 | 开发者 | 函数、模块、接口逻辑是否稳定 |
| BDD | 行为是否符合预期 | Given/When/Then 场景 | 产品、测试、开发 | 用户流程、业务规则、前端交互是否正确 |
| SDD | 意图是否被准确实现 | spec、plan、tasks、验收规则 | 产品负责人、架构师、AI Agent、开发者 | AI 是否按统一规格实现,避免跑偏 |
它们不是互相替代关系,而是层层递进:SDD 定义方向,BDD 定义行为,TDD 保证实现。

为什么 AI 编程更需要 SDD
传统开发里,人类程序员会通过经验、会议、上下文和长期沟通理解需求。但 AI Agent 没有人类团队那种持续稳定的项目记忆。即使你写了产品宪章、设计规范、AGENTS.md、CLAUDE.md,它也可能在某次任务里漏读、误解或走偏。
所以 AI 编程最大的问题不是“AI 不会写代码”,而是:AI 不知道什么是正确的;AI 不知道哪些东西不能做假;AI 不知道哪些旧问题不能改回去;AI 不知道哪些设计原则是项目底线;AI 不知道这次任务完成后应该提供什么证据。
SDD 的价值,就是把这些隐性要求变成显性规格。比如你可以在 spec 里明确写:
- 所有列表必须使用真实接口数据,不允许 mock 数据冒充完成。
- 所有按钮必须有真实交互,不允许只放静态按钮。
- 所有保存操作必须有成功、失败、加载中三种真实状态。
- 涉及 UI 的任务必须提供截图或浏览器验证结果。
- 修改后必须运行测试,不允许只说“应该可以”。
- 不得回滚已经修复的问题。
- 不得把开发工程类提示文案暴露在产品页面里。
这些要求如果只写在聊天里,AI 很容易忘。但如果进入 spec、plan、tasks 和验收门禁,就会成为开发契约。
GitHub Spec Kit:典型的 SDD 工具化案例
谈 SDD,就绕不开 GitHub Spec Kit。Spec Kit 的核心思路很明确:不要让 AI 直接从一句话开始写代码,而是通过结构化流程把想法逐步沉淀成规格、计划、任务和实现。
它的典型流程是:
- Spec:先说明要做什么,关注用户场景、目标和成功标准;
- Plan:再说明怎么做,确定技术栈、架构、约束;
- Tasks:把计划拆成可执行的小任务;
- Implement:让 AI 按任务逐步实现。
这套流程真正有价值的地方,不是多生成几个 Markdown 文件,而是让 AI 从“临场发挥”变成“按规格施工”。对于个人开发者来说,你不一定要完整照搬 Spec Kit,但一定可以学习它的思想:先写清楚产品规格,再写技术计划,再拆任务,再执行,每一步都要能回到上一层规格检查。
Superpowers:把 spec、plan、TDD 和 review 串起来
另一个很值得关注的项目是 obra/superpowers。它不是一个单纯的 SDD 框架,而是一个面向 AI Coding Agent 的技能工作流框架。它的核心不是教 AI 多写代码,而是教 AI 按一套纪律化流程工作。
从项目公开内容看,Superpowers 的基本流程大致是:先通过 brainstorming 澄清需求;从对话中提炼 spec;用户确认设计;再写 implementation plan;将任务拆小;执行时使用 TDD;任务之间进行 code review;最后完成分支收口和验证。
这套流程非常适合解释 AI 编程为什么不能只靠 Prompt。因为它把几个关键动作都强制化了:不是直接写代码,而是先澄清目标;不是一句话开干,而是先形成 spec;不是大块代码倾倒,而是拆成小任务;不是写完就说完成,而是测试和审核&查验;不是靠 AI 自我感觉,而是用证据证明。
其他工具生态与项目热度
除了 Spec Kit 与 Superpowers,我认为 OpenSpec、Aider、Cucumber-JS 也值得放到同一张表里看。它们处在不同位置,但都能帮助理解 TDD/BDD/SDD 在 AI 开发中的落点。
| 项目 | 截至 2026-06-02 抓取 Stars | 为什么相关 | 我给它的定位 |
|---|---|---|---|
| obra/superpowers | 约 215k | 技能化工程纪律、spec-first、强 TDD、review/verify | SDD + TDD 方法论框架 |
| github/spec-kit | 约 108k | constitution/spec/plan/tasks/implement 链路清晰 | 典型 SDD 工件工具包 |
| Fission-AI/OpenSpec | 约 52.3k | proposal/specs/design/tasks + delta spec 变更模型 | 团队化 SDD 工作台 |
| Aider | 约 45.7k | architect/editor 分离、自动 lint/test、git-first | 轻量 plan/test 增强型 AI 编码 |
| cucumber/cucumber-js | 约 5.3k | .feature + Gherkin + step definitions | 典型 BDD 执行层 |

Aider 虽然不是严格意义上的 SDD 工具,但它的 architect 模式把“代码推理”和“代码编辑”分成两个阶段,同时还能在每次变更后自动 lint/test,这让它更接近一种轻量版“计划 + 验证”工作流。OpenSpec 则更接近 Spec Kit 的同类,它把当前系统行为保存在 specs 中,把每次变更组织成 proposal、design、tasks 和 delta specs,这个“变更驱动”的工件模型很适合团队做长期演进。
这些方法算不算 Harness Engineering?
你问这些方法是不是都属于 Harness Engineering 的范畴,我觉得要分两层看。
如果狭义地说,TDD、BDD、SDD 本身不等于 Harness Engineering。 它们本来就是软件工程里的开发方法:TDD 偏测试驱动,BDD 偏行为验收,SDD 偏规格驱动。它们不是最近才因为 AI 出现的概念。
但如果放到 AI Coding Agent 的语境下,它们确实可以成为 Harness Engineering 的关键组成部分。 OpenAI 在 “Harness engineering: leveraging Codex in an agent-first world” 里提到,重点已经不只是写提示词,而是让仓库知识成为系统记录、提高应用和代理的可读性、通过架构和约束来引导 agent 工作;Martin Fowler 网站上的 Harness Engineering 文章也把它理解成让 coding agent 更可信的一套上下文与执行环境设计;Red Hat 的文章则把重点放在 structured context,而不是 free-form tickets。
按照这个理解,TDD、BDD、SDD 可以这样放进 Harness Engineering 里:
| 方法 | 在 Harness Engineering 里的角色 | 它约束 AI 的方式 |
|---|---|---|
| SDD | 规格 / 上下文层 | 告诉 AI 目标、边界、非目标、验收标准和禁止事项 |
| BDD | 行为 / 场景层 | 告诉 AI 用户真实行为是什么,防止只做表面 UI |
| TDD | 测试 / 验证层 | 用失败测试、回归测试、边界测试约束实现 |
| Plan / Tasks | 执行编排层 | 把大任务拆成可执行、可审核&查验、可回滚的小任务 |
| Review / CI | 反馈与门禁层 | 让 AI 必须提供证据,而不是只说“完成了” |
| AGENTS.md / CLAUDE.md / MCP / 权限 | 运行环境层 | 限制工具、权限、上下文来源和可执行动作 |
所以我的结论是:TDD、BDD、SDD 不是 Harness Engineering 的全部,但它们完全可以组成 AI 编程 Harness 的核心骨架。如果把 Harness Engineering 理解成“给 AI Agent 设计一套可控、可验证、可审计的执行环境”,那么 SDD 是上下文与规格 Harness,BDD 是行为验证 Harness,TDD 是代码验证 Harness,CI/Review 是反馈 Harness。它们组合起来,才是真正能把 AI 从 Vibe Coding 拉回工程化交付的关键。
几个我觉得最有参考价值的案例
GitHub Brain MCP Server
这是我觉得很有意思的公司实践之一。GitHub 在官方博客里,把 GitHub Brain MCP Server 作为一个“用 Markdown 当编程语言”的实验案例:作者几乎不直接编辑 Go 代码,而是编辑 README.md 与 main.md,再通过 compile.prompt.md 让 GitHub Copilot 把规格“编译”为 main.go。规格开发循环变成“编辑规格 → 让 AI 编译成代码 → 运行测试 → 再更新规格”。这是一个非常纯粹的 SDD 实验。
Superpowers
Superpowers 的实践价值在于,它把“写规格、写计划、按任务实现、每步 review、最后验证”做成了代理必须遵守的工作纪律。对我来说,这说明它不是“给模型一点提示词”,而是在构造代理行为学。
OpenSpec
OpenSpec 的亮点在于它把“规格驱动”落到了变更管理上。openspec/specs/ 保存系统当前行为,而每个 change 都会创建自己的 proposal.md、design.md、tasks.md 和 delta specs;实现完成后,再将 delta 合并回主 specs。这个模型很适合团队做审计友好、可回退、可归档的开发。
Cucumber-JS
Cucumber-JS 不是新项目,但它是 BDD 在工程里最典型、最标准化的落地形态之一。它让测试以 plain language 编写,让非开发角色也能读懂,并通过 Gherkin 语法把 Scenario / Given / When / Then 连到 step definitions 上。在 AI 时代,Cucumber-JS 的新价值不是替代 SDD,而是成为 SDD 的一个中间层。
一套适合个人开发者的落地流程
如果你正在用 AI 写前端、WordPress 插件、后台管理系统、SaaS 产品,可以采用下面这套轻量流程。
第一步:写 SDD 规格
新功能开始前,先写一份 spec.md。至少包含:功能目标、用户角色、核心场景、不做什么、数据来源、UI 状态、错误处理、性能要求、安全要求、验收标准、禁止事项。
## 功能目标
为文章可见性控制模块增加“手动添加文章并设置隐藏模式”的能力。
## 用户角色
站点管理员。
## 核心场景
管理员可以搜索文章、添加到隐藏列表、设置隐藏模式、保存配置。
## 禁止事项
不允许使用假数据展示保存成功。
不允许只隐藏详情页而不隐藏列表页。
不允许保留无效的批量设置入口。
不允许破坏分页、搜索、排除分类功能。
## 验收标准
保存后刷新页面,配置仍然存在。
前端文章列表不再显示被隐藏文章。
直接访问隐藏文章时按隐藏模式处理。
搜索结果中不显示被隐藏文章。
这一步的目的,是让 AI 不再凭感觉猜你的意图。
第二步:写 BDD 行为场景
Scenario: 管理员添加一篇文章到隐藏列表
Given 管理员已经进入插件设置页
And 文章 A 当前没有被隐藏
When 管理员搜索文章 A 并添加到隐藏列表
And 设置隐藏模式为“仅登录可见”
And 点击保存
Then 页面应该显示真实保存成功提示
And 刷新后文章 A 仍然在隐藏列表中
Scenario: 被隐藏文章不出现在前端列表
Given 文章 A 已被设置为隐藏
When 访客打开首页文章列表
Then 文章 A 不应该出现在列表中
And 分页数量不应该因为隐藏文章而显示异常
BDD 场景要尽量站在用户行为角度,而不是实现细节角度。不要写“调用 filter_posts() 方法后返回 false”,而应该写“访客打开文章列表时,看不到被隐藏文章”。
第三步:把关键逻辑转成 TDD 测试
BDD 适合描述行为,但具体到代码层面,仍然需要 TDD。例如文章隐藏判断函数:
public function is_post_hidden($post_id, $context) {
// implementation
}
你可以先写测试:文章不在隐藏列表时返回 false;文章在隐藏列表且当前用户未登录时返回 true;文章在隐藏列表但管理员访问时返回 false;排除分类下的文章不受隐藏规则影响;无效 post_id 不应该导致 fatal error。这些测试先失败,再实现代码。这时候 AI 不能随便发挥,因为每一个边界都被测试卡住了。
第四步:让 AI 按 plan 拆任务
不要让 AI 一次性做完所有东西。一个好的 plan 应该拆成小任务:调整设置数据结构;实现文章添加与搜索;实现保存与读取;实现前端列表过滤;实现详情页访问限制;补充测试;做 UI 与真实浏览器验收。每个任务都要有相关文件、输入输出、验收标准、测试命令、禁止事项和完成证据。任务越小,AI 越不容易跑偏。
第五步:建立验收门禁
AI 说“完成了”不等于真的完成。一个合格的验收报告至少应该包括:修改了哪些文件;实现了哪些规格;哪些 BDD 场景已验证;哪些 TDD 测试已通过;运行了什么命令;有没有截图;有没有真实数据验证;有没有遗留问题;有没有回滚风险。

TDD、BDD、SDD 应该怎么组合
最推荐的组合方式是:先 SDD,后 BDD,再 TDD。也就是先用 SDD 写清楚规格,再用 BDD 写清楚用户行为,最后用 TDD 写清楚代码测试。
如果是一个新项目,可以这样做:产品宪章 → spec.md → plan.md → tasks.md → BDD 场景 → TDD 测试 → 实现 → 验收报告。
如果是一个小功能,可以简化为:迷你 spec → 3 个 BDD 场景 → 关键 TDD 测试 → 实现 → 截图和测试结果。
如果是一个 bugfix,可以更简单:复现规格 → 失败测试 → 修复 → 回归测试 → 防回滚说明。重点不是形式,而是让每一步都有明确证据。
常见误区
第一个误区:以为 TDD 就是补测试
不是。先写代码再补测试,最多叫“有测试”,不叫测试驱动。真正的 TDD 必须先看到测试失败,再写实现。
第二个误区:以为 BDD 就是写 Given/When/Then
也不是。如果场景写得全是实现细节,而不是用户行为,那只是换了格式的测试说明。BDD 的核心是让业务、产品、测试、开发对系统行为形成共同理解。
第三个误区:以为 SDD 就是写文档
更不是。传统文档经常写完就没人看。SDD 的关键是让规格进入开发过程,成为 AI 实现、任务拆解、测试生成、验收检查的源头。
第四个误区:以为用了 AI 就不需要这些方法
恰恰相反。AI 越强,越需要规格和门禁。因为 AI 生成速度越快,错误扩散也越快。没有 SDD、BDD、TDD,AI 可能在几分钟内帮你制造一堆“看起来完成”的技术债。
给 AI 编程的一句话建议
不要再把 AI 当成一个“你说一句,它写一堆”的代码生成器。更好的方式是:用 SDD 告诉它目标和边界;用 BDD 告诉它用户行为;用 TDD 告诉它代码正确性;用验收门禁要求它证明自己真的完成了。
未来的软件开发,很可能不是“谁更会写代码”决定胜负,而是谁更会定义规格、拆解任务、设计验证、控制质量。AI 可以帮你写得更快,但规格、行为和测试,才是让产品真正可靠的底座。
TDD 让代码写稳。BDD 让功能做对。SDD 让 AI 不跑偏。这三者合起来,才是 AI 编程从“看起来能用”走向“真正可交付”的关键。
参考来源与延伸阅读
为了避免正文读起来像论文,我没有把每句话都做成密密麻麻的脚注。下面这些是我整理这篇文章时最主要参考的官方文档、项目仓库和实践文章,适合继续深挖。
- GitHub Spec Kit 仓库与 README:Spec Kit 的整体工作流、目录结构和命令链路。
- GitHub Spec Kit:spec-driven.md:规格驱动开发的核心方法论说明。
- Spec Kit spec-template.md:用户故事、边界、功能需求、成功标准等规格模板。
- GitHub Blog:用 Markdown 作为编程语言构建 GitHub Brain MCP Server:一个很典型的 SDD 实验案例。
- Microsoft Learn:规范驱动开发与 GitHub Spec Kit 入门:中文学习材料。
- obra/superpowers 仓库:把 brainstorm、plan、implement、review、verify 技能化的代理开发方法。
- Superpowers brainstorming 技能:实现前先形成设计文档。
- Superpowers test-driven-development 技能:严格 TDD 纪律。
- Cucumber BDD 文档:BDD 的 discovery、collaboration、examples。
- Gherkin Reference:Given / When / Then 等语法结构。
- IBM:What is Test-Driven Development:TDD 与 red-green-refactor 循环说明。
- OpenSpec 仓库:proposal、design、tasks、delta specs 的规格化变更流程。
- Aider architect/editor 模式文档:轻量 AI 编码与验证工作流。
- OpenAI:Harness engineering: leveraging Codex in an agent-first world:Agent-first 开发里的 Harness Engineering 实践。
- Martin Fowler:Harness engineering for coding agent users:从 context 与 harness 的角度理解 coding agent 可信度。
- Red Hat:Harness engineering: structured workflows for AI-assisted development:用结构化上下文替代自由文本任务。


评论