TDD 是复杂业务系统中 Vibe Coding 的最好帮手
TDD 是复杂业务系统中 Vibe Coding 的最好帮手
在 AI 帮你写代码之前,你得先给它一个不会跑偏的轨道。
现实世界里,几乎没有“从零开始的 Vibe Coding”
如果你刷过一些 AI 编程的 KOL 内容,很容易产生一种错觉:
打开编辑器,丢给 AI 一个需求,代码像瀑布一样倾泻而出,服务一跑就成功。
但现实工作中几乎不会是这样。
大多数工程师面对的,是陈年老屎山:
- 业务逻辑盘根错节
- 依赖的基础设施众多(RPC、消息队列、数据库、第三方服务)
- 本机环境要么跑不起来,要么跑起来了却无法完整运行关键链路
在这种系统中,不仅人类很难一眼理解全貌,AI 更不可能“通读全局”后一次写对代码。
这也是为什么,直接用 Vibe Coding 往往会遇到两个致命问题:
- AI 无法通过运行结果判断自己是不是写对了
- 一次修改,很容易破坏原本还能工作的老逻辑
问题不在 AI,而在反馈
很多人觉得:
AI 写的代码不靠谱。
但更准确的说法是:
AI 缺少足够短、足够确定的反馈回路。
在复杂系统中:
- 前端工程可能依赖完整的后端环境,本机根本跑不起来
- 后端服务可能需要连 RPC、SQL、缓存、鉴权、配置中心
如果代码不能被快速、稳定地执行,AI 就失去了最重要的“自我校正”能力。
TDD,恰好是 Vibe Coding 缺失的那块拼图
TDD(Test Driven Development)在很多团队里争议很大。
但在 AI 时代,它反而变成了一种极其适合 Vibe Coding 的工程工具。
原因很简单:
测试,就是 AI 能理解、也能验证的“需求规格说明书”。
相比自然语言需求:
- 测试是可执行的
- 测试是确定性的
- 测试失败时,反馈极其明确
这正是 AI 最擅长处理的输入形式。
在跑不起来的系统里,AI 如何自我纠错?
前端场景
在一些复杂前端工程中:
- 构建链路复杂
- 本机无法完整启动后端
- 页面依赖大量接口和配置
如果页面能跑起来,当然可以借助 Puppeteer、Playwright 之类的工具,让 AI 通过 e2e 测试自我修正。
但更多时候,连这一步都做不到。
这时,组件级 / 函数级的单元测试就成了唯一可行的反馈方式:
- 对输入和输出进行约束
- 对边界条件进行明确描述
- 将 UI 逻辑从真实环境中剥离出来
后端场景
后端更是如此:
- RPC 调用
- SQL 查询
- 外部服务依赖
AI 不需要真的连上这些系统。
你只需要:
- 用 Mock / Stub 固定住外部行为
- 用测试定义清楚“在这些前提下,应该得到什么结果”
剩下的逻辑推导,交给 AI。
我在复杂系统里使用 Vibe Coding + TDD 的方式
1. 人来负责架构,AI 只做优化
第一步,不要让 AI 从零设计复杂系统。
我通常会:
- 自己先拆好模块边界
- 明确每个模块的职责
- 定义接口或函数签名
然后让 AI:
- 优化命名
- 补充边界情况
- 细化功能描述
这一阶段,只产出接口和约定,不产出具体实现。
2. 在函数级 / 包级进行多轮 Vibe Coding
当边界被固定后,Vibe Coding 才真正开始变得安全。
一个常见流程是:
先有测试
- 可以自己写关键测试
- 也可以让 AI 根据功能描述生成测试
再让 AI 写实现逻辑
强制执行测试作为反馈
在 rules 文件或系统提示中明确要求:
每次修改代码后,必须执行
xxx命令运行单元测试
测试失败时:
- 错误信息就是最清晰的 Prompt
- AI 可以据此反复修正实现
3. 用测试保护“已经能工作的老代码”
在老系统里,最怕的不是新代码写不出来,而是:
新代码悄悄把旧逻辑弄坏了。
测试在这里起到的是“安全网”的作用:
- 新一轮 Vibe Coding 只要通过测试
- 就能确信没有破坏既有行为
这让多次、持续地使用 AI 改代码变得可行。
写在最后
Vibe Coding 真正的风险,并不在于 AI 会不会写代码。
而在于:
- 你是否给了它一个可验证的目标
- 你是否提供了足够短的反馈回路
在复杂业务系统中,
TDD 不是为了“代码更优雅”,而是为了让 AI 不迷路。
当测试成为需求的一部分,
Vibe Coding 才不再是碰运气,而是一种可持续的工程实践。