AI 写代码又快又好?你可能少了最关键的一步

发布时间:2026/6/23 11:12:03
AI 写代码又快又好?你可能少了最关键的一步 AI 写代码又快又好你可能少了最关键的一步AI 10 分钟写完一个 CRUD 模块编译通过启动正常上线一周后出了 bug——某个边界条件没人测过AI 也没写测试。目录AI-coding 的工程化问题测试全景不只是找 BugTDD先写测试再写代码SDD两种含义同一个目标OpenSpec 和 Superpowers 如何内建测试给 AI-coding 开发者的落地建议AI-coding 的工程化问题大多数人用 AI 写代码的流程是这样的把需求丢给 AIAI 吐出一堆代码自己跑一下能启动就算成功上线这个流程最大的问题不是 AI 写得不好而是是是没有质量关卡是是。AI 产出的代码碰巧能跑但没人验证它在边界条件下是否正确也没人确认它和其他模块拼在一起会不会炸。我之前用 Claude Code 开发一个客户管理模块10 个任务全部用子代理并行跑完编译全过看起来很顺利。结果部署时才发现SQL 脚本的列数对不上、JAR 包没重新打包、一个字段忘了赋值。这些问题在编译通过的表象下藏了好几天。这就是 AI-coding 的工程化问题AI 能写代码但不会替你做工程。目前有两个工具在尝试解决这个问题OpenSpec 规格驱动开发框架。核心理念是先想清楚再写代码——需求探索 - 生成提案 - 执行编码 - 质量验证 - 归档沉淀。它管的是做什么。Superpowers Claude Code 的插件把软件工程最佳实践固化成 AI 可遵循的工作流。核心理念是 Process over Prompt——流程大于提示词。它管的是怎么做。两者都指向同一个被忽略的环节测试。测试全景不只是找 Bug很多人对测试的理解停留在找 Bug。但测试远不止于此——它是一门涉及质量评估、风险控制与成本管理的系统性工程。测试金字塔经典的测试策略遵循金字塔结构底层60-70%单元测试 。针对单个函数或方法隔离外部依赖运行速度极快毫秒级。数量最多是基石。中层20%集成测试 。验证模块之间的交互——API 调用、数据库读写、消息队列。会连接真实资源速度较慢。顶层10%端到端测试E2E 。模拟真实用户操作成本最高、速度最慢、维护最贵。对 AI-coding 来说单元测试是第一道防线。AI 写的代码逻辑可能对也可能不对单元测试能在毫秒级告诉你答案。单元测试 vs 集成测试维度单元测试集成测试测试对象单个函数/方法/类多个模块之间的接口与交互外部依赖全部模拟Mock尽量真实连接数据库/网络运行速度极快毫秒级较慢秒级甚至分钟级数量数量庞大成千上万数量较少对应核心业务流程定位 Bug精确立刻知道哪个函数错了模糊只知交互失败需排查两端一个实用原则如果 Bug 在集成测试中被发现先补一个单元测试来复现它修复后再跑集成测试。这能确保同一个 Bug 永不复发。测试四原则尽早测试Shift-Left 测试不应等编码结束才开始需求分析阶段就能发现问题。越早修成本越低。杀虫剂悖论 总用相同的测试用例系统会对这些 Bug 免疫。必须定期更新测试用例。缺陷集群性 80% 的崩溃集中在 20% 的核心模块。测试资源应重点轰炸复杂度最高的区域。上下文依赖 没有万能测试方案。银行支付系统的测试强度不能照搬企业内部 OA。为什么 AI-coding 更需要测试AI 不理解业务意图只理解模式匹配。它会写出看起来正确但逻辑有漏洞的代码——因为它是在模仿训练数据中的模式而不是在理解你的业务规则。测试的作用不是验证 AI 写对了什么而是是是告诉 AI 应该写什么是是。当你先写好测试用例AI 的行为边界就被框死了它必须产出能通过这些测试的代码。这就是 TDD 的核心价值。TDD先写测试再写代码TDDTest-Driven Development测试驱动开发是一种测试先行的开发方法论。它的核心信条在编写任何生产代码之前先编写一个会失败的测试用例。红-绿-重构TDD 严格遵循一个极短循环红Red 先写一个测试调用你尚未实现的函数。运行测试它必然失败。目的确认测试有效同时明确当前任务边界。绿Green 写刚好能让测试通过的代码。不要考虑优雅唯一目标是让测试变绿。目的尽快获得可工作的状态。重构Refactor 测试通过后放心优化代码结构。重构过程中时刻运行测试改坏了立刻知道。每次循环通常只持续 1-5 分钟小步快跑。TDD 在 AI-coding 中的价值用 AI 写代码时TDD 的意义变了。传统开发中TDD 是为了驱动设计在 AI-coding 中TDD 是为了了了约束 AI 的行为边界了了。想象一下你让 AI 写一个客户导出功能。如果不先写测试AI 可能给你一个能跑但缺少边界处理的实现——比如没考虑空数据、没考虑特殊字符、没考虑权限校验。你得自己一个个发现这些问题。但如果你先写好测试导出空数据时应该返回空文件而不是报错客户名称包含逗号时 CSV 应该正确转义没有导出权限的用户应该被拒绝AI 就必须产出能通过这些测试的代码。测试用例变成了 AI 的行为规范。真实教训TDD 缺失的代价我在用 Superpowers 开发客户管理模块时10 个任务全部跳过了 TDD——先写代码后补测试。结果边界条件遗漏测试没有驱动设计某些异常路径根本没覆盖到兼容性问题发现太晚Spring Boot 4.0.6 移除了 WebMvcTest 和 MockBean直到补测试时才发现测试变成了验证而非定义后补的测试只是在确认现有代码能跑而不是定义代码应该怎样跑事后补测试不等于 TDD。TDD 的精髓是测试先行——测试用例定义了期望行为代码去满足这个期望。顺序反了效果就完全不同。SDD两种含义同一个目标SDD 在 AI 编程领域至少有两个含义它们指向同一个目标 : 让开发过程有章可循Spec-Driven Development规范驱动开发如果说 TDD 是用测试用例驱动开发SDD 就是用规范文档驱动开发。它主张在写任何代码之前先用结构化的自然语言把软件要做什么、为什么做清晰定义出来。核心工作流指定Specify 定义用户故事、验收标准计划Plan 确定技术架构和实现方法任务Task 将计划拆解成具体的开发任务实现Implement 根据规范和计划编写代码OpenSpec 就是这个理念的工程化实现。它的 spec.md 文件用 SHALL/MUST 这样的正式语言定义系统行为每个 Scenario 都是一个可验证的行为契约。Subagent-Driven Development子代理驱动开发这是 Superpowers 插件里的 SDD。它的工作方式是为计划中的每一个任务都启动一个全新的、独立的子代理去执行。每个任务在干净的环境中进行避免不同任务间的上下文污染。任务完成后还有两阶段评审先检查是否符合规范再检查代码质量。SDD 和 TDD 的关系它们不是互斥的而是互补的SDD 管做什么 需求 - 规格 - 设计 - 任务清单TDD 管做对没 每个任务内部RED - GREEN - REFACTOR一个完整的开发流程应该是先用 SDD 写好规范再用 TDD 保证代码质量。OpenSpec 的 spec.md 中每个 Scenario 可以直接映射成测试用例。比如 spec 里写了按筛选条件导出和无筛选条件导出两个场景那就是两个测试用例的骨架。OpenSpec 和 Superpowers 如何内建测试OpenSpec 的测试集成OpenSpec 在三个地方把测试嵌入了开发流程spec.md 的 Scenario 每个需求下面的 Scenario 天然就是测试用例。写 spec 的时候就在写测试骨架。tasks.md 的 TDD 阶段 任务清单的第一组任务就是 TDD Red Phase——先写失败测试。Verify 阶段 编码完成后跑测试验收。测试不过不允许归档。这种设计让测试不是一个独立的活动而是开发流程的有机组成部分。Superpowers 的测试集成Superpowers 通过 test-driven-development skill 强制 AI 先写测试。如果 AI 在没有先编写测试的情况下就开始写实现代码Superpowers 会直接打断并阻止它。在子代理驱动开发流程中每个任务应该遵循RED写失败测试- GREEN写实现- REFACTOR优化- 提交。审查子代理还会验证测试是否先于实现。但实际执行时这个流程经常被跳过。我在复盘中发现所有 10 个实现任务都是先写代码后补测试审查子代理也主要做逐行对比规范没有深入检查测试覆盖。两者对比维度OpenSpecSuperpowers测试来源spec.md 的 Scenario 自动映射需要手动编写或由 TDD skill 驱动强制程度Verify 阶段卡关TDD skill 可被跳过测试范围偏向验收级别场景驱动偏向单元级别代码驱动适用阶段需求定义阶段就开始编码执行阶段才介入理想状态用 OpenSpec 的 spec 定义验收场景用 Superpowers 的 TDD skill 驱动单元测试编写。两者配合测试覆盖面最全。给 AI-coding 开发者的落地建议1. 用 spec.md 写 Scenario每个 Scenario 就是一个测试骨架不管你用不用 OpenSpec在动手写代码之前先花 10 分钟列出这个功能的核心场景。每个场景用 WHEN/THEN 格式写一句话。这不只是文档这是你后面写测试用例的骨架。比如你要做一个客户导入功能WHEN 用户上传了格式正确的 Excel THEN 系统导入成功并返回导入数量WHEN 用户上传了空文件 THEN 系统返回错误提示WHEN Excel 中有重复客户名 THEN 系统跳过重复项并报告三个场景三个测试用例10 分钟搞定。2. 让 AI 先写测试再写实现如果你用 Superpowers开启 TDD skill 即可。如果不用也可以手动约束每次给 AI 下需求时加一句先写测试用例确认测试失败后再写实现代码。这个简单的约束能显著提升 AI 产出的代码质量。因为测试用例定义了边界AI 就不会天马行空地自由发挥。3. 集成测试不要跳过AI 写的单元测试可能全绿但模块拼起来会炸。原因很简单单元测试用 Mock 隔离了外部依赖但真实运行时模块之间是要互相调用的。在每个功能模块开发完成后跑一次集成测试——启动真实数据库调真实 API验证数据流转是否正确。这比部署后才发现问题要便宜得多。不需要一步到位。先从核心业务逻辑的单元测试开始覆盖关键路径再逐步补充集成测试。写在最后AI 写代码快不快不重要重要的是写出来的代码经不经得起改。没有测试的 AI-coding 就像没有安全带的赛车——直线跑得快弯道翻得也快。TDD 给你安全带SDD 给你导航单元测试和集成测试给你双保险。测试不是 AI-coding 的附加项而是从玩具到工程的分水岭。