很多团队已经习惯用 AI 加速写功能,却没有把同样的精力放到测试和回归环节。结果就是,代码产出速度变快了,返工速度也一起变快了。这一课要建立的不是“让 AI 帮我多写几条测试”,而是把 AI 变成验证资产的放大器。
真实研发场景
功能写完不等于交付安全,真正决定信心的是验证集合
一个接口改动刚完成时,工程师最常见的感受是“主流程我已经手动跑通了”。问题在于,后端行为从来不只包含主流程。同步响应要不要验证结构化字段,流式接口要不要验证多块输出顺序,检索不到知识时要不要验证 fallback 分支,只读 SQL 预览是否要覆盖危险输入,工作流失败时是不是要暴露失败步骤。没有测试和回归集合时,这些问题几乎都只能靠人脑记忆。
AI 在这个阶段的价值并不是替你发明业务真相,而是帮助你更系统地把“应该验证什么”枚举出来。
本课真正想做的是“先锁行为,再补自动化”
测试写不好,往往不是因为不会写断言,而是因为还没把行为讲清楚。只要行为矩阵先稳定下来,AI 就很适合帮助你:
- 列举正常路径、边界路径、异常路径
- 生成测试数据和示例输入
- 起草测试命名和断言方向
- 组织回归清单和最小 eval 集合
传统做法的痛点
最容易丢的不是代码,而是验证资产
| 看起来节省了什么 | 实际付出的代价 |
|---|---|
| 少写几条测试 | 需求一变就不知道哪些行为受影响 |
| 只手工点一下接口 | 回归结果不可复现,团队无法共享信心 |
| 只测 happy path | 异常与边界问题在联调或上线后才暴露 |
| 没有统一回归清单 | 每次发布都靠个人经验回忆 |
测试与回归最大的价值,不是“多一道形式化步骤”,而是把系统行为从个人记忆转成团队资产。
AI 参与测试时最常见的三个问题
- 直接让 AI 生成大量脆弱测试,断言全贴实现细节
- 没先列行为矩阵,导致生成结果只覆盖表面路径
- 不实际运行测试,就把“看起来合理”当成通过
AI 能提效到哪一步
AI 最适合承担的验证动作
- 场景枚举:把主路径、边界和异常路径列完整
- 样例生成:补请求体、异常输入、伪造数据
- 断言草稿:帮助确定应该验证哪些行为,而不是哪些私有细节
- 回归清单整理:把每次修过的问题吸收到稳定集合里
不能直接外包给 AI 的部分
| 决策 | 为什么必须人工判断 |
|---|---|
| 什么才是业务正确行为 | 需要回到真实需求与契约 |
| 哪些断言足够稳定 | 需要知道团队是否接受内部实现变化 |
| 哪些用例值得自动化 | 取决于变更频率、失败成本和维护成本 |
| 测试是否真的通过 | 必须依赖真实运行结果 |
一个简单判断是:AI 可以帮你扩大“看见的行为面”,但不能替你定义“什么叫正确”。
推荐工作流
先写行为矩阵,再写测试代码
推荐先把要验证的内容分成三层:
- 主流程:这条能力在理想路径下的正确输出
- 边界条件:空值、极端值、少量/大量输入、权限差异
- 异常路径:非法输入、下游失败、无结果、超时或降级
五步验证闭环
| 步骤 | AI 产出 | 人工要做什么 | 验证方式 |
|---|---|---|---|
| 1. 锁行为 | 行为矩阵草稿 | 删除无价值场景,补高风险路径 | 是否覆盖主、边界、异常三层 |
| 2. 造样例 | 请求体、伪数据、错误输入 | 确认贴合真实业务 | 数据是否可直接进入测试 |
| 3. 起断言 | 测试命名、断言候选 | 过滤对实现细节过强的断言 | 断言是否描述业务行为 |
| 4. 组织回归 | 最小回归清单或 eval 草稿 | 区分自动化与手工检查 | 是否形成可重复集合 |
| 5. 真实运行 | 测试执行与结果记录 | 根据失败调整测试或代码 | 真实结果而不是猜测 |
一个适合测试阶段的输入模板
当前功能或改动:
必须保持的行为:
已知边界条件:
已知失败路径:
请输出:
1. 行为矩阵
2. 高价值测试用例
3. 回归清单草稿
与仓库代码和模板的映射
- 控制器行为验证:
../demo/src/test/java/com/example/ainative/chat/controller/ChatControllerTest.java适合观察同步响应与 SSE 输出如何被分别验证。 - 服务层行为验证:
../demo/src/test/java/com/example/ainative/chat/service/ChatServiceTest.java适合讨论“对外行为”与“内部实现细节”断言的区别。 - RAG fallback 行为:
../demo/src/test/java/com/example/ainative/knowledge/rag/RagServiceTest.java适合练习正常路径与无知识路径如何一起覆盖。 - 混合检索与只读 SQL:
../demo/src/test/java/com/example/ainative/knowledge/retrieve/HybridRetrieverTest.java、../demo/src/test/java/com/example/ainative/dataassistant/controller/SqlAssistantControllerTest.java适合观察异常与安全边界如何变成断言。 - 最小回归评测:
../demo/evals/chat/basic.yaml、../demo/evals/rag/grounded-answer.yaml、../demo/evals/tools/sql-preview.yaml适合说明“回归”不一定只有单元测试,也可以是结构化 eval 样例。 - 对应练习:
../课后练习/第5课/练习.md
常见误用与风险
误用一:让 AI 一次性生成很多测试,但没人先定义行为
这样得到的测试通常像实现镜像,而不是业务保护网。
误用二:只有 happy path,没有边界和异常
AI 会倾向于先给出“看起来正常”的路径,工程师必须主动补齐反例。
误用三:测试不运行,只看文本质量
测试代码是否有价值,最终只取决于真实执行结果。
误用四:回归清单只存在聊天记录里
没有沉淀成文件的回归经验,几乎等于下次还要重想一遍。
课后练习
建议直接在 ../课后练习/第5课/练习.md 中完成本课练习,并使用 ../课后练习/通用提交模板.md 保留 AI 输入、人工删改和验证结果。
如果你只做最小版交付,也至少保留四样东西:结构化输入、AI 产出摘要、人工判断记录、最终验证结果。
基础题
选 demo/ 中一个已有测试较少的行为,先补一份主路径 / 边界 / 异常矩阵。
进阶题
让 AI 基于该矩阵生成测试样例或回归清单,再人工删掉低价值项并说明原因。
挑战题
至少运行一次真实测试或 eval,并记录哪些行为被保护住了,哪些仍然缺口明显。