实践3|用 Claude Code 从需求文档走到集成测试打通真数据库
上一次实践只做了一件事:改一个工具类,加 mock 测试,再补一个真接口打通的集成测试。这次链路长很多——从"读需求文档"开始,走到"跑通连真数据库的集成测试",全程扔给 Claude Code。这一篇有意识地把 TDD 作为主线走了一遍,需求消化这个上游动作也换了个玩法:让 AI 先把需求写成一份可回溯的 md,再切新会话开工。一、读需求:让 AI 先替我做一份结构化笔记需求来自公司协同文档平台上一个需求单页面。我通常的做法是打开浏览器、复制文字、边看边写代码。这次换了个玩法。第一步就一句话:打开这个需求单链接,理解需求,生成一份 md 文档,放到某目录/RRR_xxxx_需求名_需求号.md,用需求名当文件名。它做的事:拉页面正文提取"需求原文 / 成功标准 / 待确认问题 / 技术方案 / 实施步骤 / 相关成员"这些段落在"待确认问题"里主动列了 6 条:口径定义、userId 到底指哪个、批量导入是否原子、上限值是不是随用户等级变化、错误码规范、现有接口清单落成一份完整 md,还带 checklist 勾选框关键在第 3 步——它没有直接开始"实施步骤",而是先把我看需求时会漏问的东西列出来了。这些问题里有几个我是真没想到(比如"userId 是登录用户 id 还是被保用户 id",两者在替家人签约的场景下不一致)。写完 md 我 Task 列表里加了一条TDD 第 1 步:写单测(失败),把 md 文档路径贴进去,切另一个新会话开工。这个动作看上去只是"把需求整理了一遍",隐藏收益有两个。一是 AI 主动列出的待确认清单,比我自己看需求时的清单更全——我看需求会带着自己的假设跳读,它是无假设通读。二是这份 md 成为会话之间的桥:下一节会讲,切到新会话开工时,我不用再复述需求,一句"按这份 md 实现"就够。二、复用上一次逆向出来的文档新会话里我说:请按 TDD 方式,完成RRR_xxxx_需求名.md(在上级目录)这个需求它做的第一件事不是搜代码——是先去读docs/模块名.md。那份文档是实践1里我让它逆向陌生业务模块生成的,包含时序图、错误码对照、代码位置速查。于是它 30 秒之内就定位到:校验应该塞在哪个 Controller 的哪个方法里(有一段FIXME 不应该写在这里,待重构的注释,我这次不管)从当前应用层走到权威数据服务的完整链路穿了 4 个模块表结构 / 字段口径都能在文档里直接查到实践1 存下来的那份逆向文档,在实践3 里回收利益了。不是每次会话都从零开始摸索,前面的会话产出真的能被后面复用。三、TDD 主线,但不是纯洁的 TDD需求确认好,动手前我先让它建分支——4 个要动的子仓库,都从 prod 拉feature/xxx-260709。这里踩了个小坑:脚本默认会 push 到远程,但我本机到内网 gitlab 网络不通,git fetch卡了一分多钟才超时。后面直接从本地已有的origin/prodref建分支(不 fetch),跳过网络。然后主线是 TDD 的 6 步:步动作预期状态1写应用层的 Mockito 单测(校验器 3 个用例:低于阈值 / 等于阈值 / 高于阈值)红2连接层加转发方法编译过3开放接口层加转发方法编译过4权威域服务加 mapper SQL + Service 方法编译过5应用层校验器把逻辑填进去、Controller 接入调用红→绿6跑单测3/3 绿严格 TDD 说"先写测试到编译不过为止"。我没这么干。我先写了目标类和方法的空骨架(方法体是// TODO),让测试能编译过、但运行时全红。这样比"红到编译错误"更容易看出哪个断言在期望什么。跑第一遍单测的时候 3 个用例全红,红得很干净——两个 “should throw” 的因为空实现不抛,一个 “should pass” 的因为空实现根本没调 Feign(Wanted but not invoked是这个测试给我的信号)。补完 4 层链路 + 应用层校验器逻辑,再跑一遍,3/3 绿。