ApiCabin

← 回到教程

让 AI 编写的代码始终可测试:开发者实战教程

从零开始 · ZH · 2026-10-24 · 141 次阅读

为什么 AI 代码更需要可测试性

AI 能快速生成函数、接口适配层和业务流程,但“能运行”不等于“可维护”。常见问题包括:函数职责过多、数据库或网络调用写死、错误处理缺失,以及测试只能依赖真实外部服务。一旦需求变化,团队很难判断修改是否破坏了既有行为。将可测试性作为 AI 编程的首要约束,可以把生成速度转化为长期交付效率。

第一步:先写行为,再让 AI 写实现

不要只输入“实现订单折扣功能”。先明确可观察的行为:输入是什么、输出是什么、异常如何表示、边界条件有哪些。例如,会员折扣应接收订单金额和会员等级,返回最终金额;负数金额必须报错;折扣结果不得小于零。把这些规则写成测试用例或验收清单后,再要求 AI 根据清单实现函数。

  • 正常路径:普通会员与高级会员分别得到预期价格。
  • 边界路径:金额为零、折扣为零、折扣达到上限时行为明确。
  • 异常路径:非法等级、负金额和缺失字段都能得到稳定结果。

提示 AI 时可以直接要求:“先输出测试用例,再实现最小代码使测试通过;不要访问网络、文件系统或数据库。”这样生成结果会自然倾向于纯函数和清晰接口。

第二步:把副作用隔离在边界层

最容易测试的是纯函数:相同输入总是产生相同输出,不读取全局状态,也不直接调用外部服务。将价格计算、权限判断、数据转换等核心规则放入纯函数;将 HTTP 请求、缓存、日志、数据库和时间读取放到边界层。业务函数通过参数接收这些依赖,而不是在函数内部自行创建。

例如,不要在服务函数中直接调用支付 SDK。应传入 paymentClient 接口,再在生产环境传入真实客户端,在测试环境传入可控的假实现。这样测试可以模拟成功、超时和拒绝支付,而不产生真实费用或依赖不稳定网络。

第三步:要求 AI 保持接口小而明确

让 AI 一次生成大型“万能服务”通常会降低测试质量。每个函数只完成一个业务动作,参数使用明确的数据结构,返回值统一表达成功与失败。避免同时返回 null、抛异常和字符串错误三种风格。接口越小,测试组合越少,审查越容易。

在代码生成请求中加入约束:单个函数只处理一个职责;不得隐藏读取环境变量;所有时间、随机数和外部客户端均可注入;为公共函数补充输入、输出和失败场景。随后要求 AI 为每个公共函数给出至少一个正常测试和一个失败测试。

第四步:用分层测试验证生成结果

单元测试负责验证纯业务规则,速度快且覆盖边界条件;集成测试验证模块与数据库、消息队列或第三方接口的连接方式;端到端测试只覆盖少量关键用户路径。不要试图用端到端测试弥补缺失的单元测试,否则定位失败会很困难。

  • 单元测试:使用假对象验证业务决策与错误处理。
  • 集成测试:验证序列化、迁移和接口契约。
  • 端到端测试:覆盖注册、支付或发布等核心流程。

对 AI 新增的每段逻辑,先运行相关单元测试,再运行静态检查和格式化工具。若 AI 修改了既有代码,额外要求它说明哪些行为没有改变,并为修复的问题补一个能先失败、后通过的回归测试。

第五步:建立可复用的 AI 编码工作流

团队应把测试规则放入项目说明文件:测试命令、目录约定、命名规范、禁止直接访问的依赖,以及提交前必须通过的检查。使用 ApiCabin 时,独立开发者和小团队可以通过一个按量付费的密钥接入多种模型,并可配合 Claude Code、Codex、Gemini CLI 或 OpenAI 兼容 SDK 使用。你可以选择 Claude Sonnet 5.5 或 Gemini 3.1 Pro 作为代码审查或测试补全的示例,但最终仍应以本地测试结果为准。

最后,把 AI 当作结对编程伙伴,而不是代码发布者:先给规格,要求测试,再审查边界与依赖,最后让自动化检查把关。想将这一流程接入现有工具链,可以注册 ApiCabin 后从一个小模块开始验证。

想照着试一遍?注册就有 ¥2.00 体验额度。 注册

同一面墙上的