Skip to content

用 Codex 补测试与建立验证门槛

“让 Codex 加测试”很容易得到覆盖率变高、信心却没有增加的测试。本页的目标是让测试证明用户行为或业务规则,而不是把当前实现原样抄进断言。

第一步:先读测试约定

text
只读分析当前项目的测试体系:
- 使用哪些框架和命令;
- 单元、集成、端到端测试分别放在哪里;
- fixture、mock、数据库和浏览器怎样初始化;
- CI 实际运行哪些检查;
- 找两个与目标代码最相似的高质量测试作为范例。

不要修改文件。

然后要求它指出命令来自 package.json、构建文件或 CI 配置,而不是凭经验推荐。

第二步:先写测试意图

以“价格计算”为例,差的意图是“覆盖 calculateTotal”。好的意图是:

  • 正常商品合计正确;
  • 数量为零时不产生负数;
  • 折扣只作用于允许的商品;
  • 金额使用项目规定的舍入方式;
  • 无效输入返回现有错误类型。

提示:

text
为 [行为] 设计最小测试集合。先列出每个测试防止什么回归,再写代码。优先验证公开行为,不要绑定私有函数、调用次数或无关 DOM 结构。

第三步:确认测试在修复前会失败

回归测试必须能区分有 Bug 和无 Bug 的版本。让 Codex先运行测试并保存失败证据:

text
先只添加回归测试并运行它。确认它因目标 Bug 失败,而不是因为语法、fixture 或环境错误。把失败断言摘要给我,然后再修改生产代码。

如果测试一开始就通过,可能是:

  • 没有触发真实问题;
  • 断言太弱;
  • 测错了层;
  • 当前分支已包含修复;
  • 复现条件缺失。

第四步:避免无价值测试

重点检查以下反模式:

  • 只断言函数被调用,没有断言结果;
  • mock 掉了真正出错的层;
  • 测试复制生产实现的计算步骤;
  • 快照巨大且无人审查;
  • 通过 sleep 等待异步行为;
  • 为通过测试改变生产语义;
  • 捕获异常但没有断言类型和内容;
  • 只覆盖成功路径。

可以让 Codex自审:

text
审查刚添加的测试:它们是否会在实现退化时真正失败?指出过度 mock、恒真断言、重复实现和时序不稳定风险,并做最小调整。

第五步:建立验证阶梯

每次改动从小到大运行:

  1. 单个新增测试;
  2. 当前测试文件;
  3. 当前模块或包;
  4. 类型检查/lint/编译;
  5. 相关集成或端到端测试;
  6. 项目完整构建。

不要每改一行都跑最昂贵的全套检查,也不要只跑单测就声称整体可发布。

提示模板:

text
按成本从低到高列出本次改动的验证阶梯。先运行最小项;只有通过后才扩大。每一步报告命令、退出码和关键统计,失败时停止并定位。

测试 UI

UI 测试按层分工:

  • 纯函数和状态转换用单元测试;
  • 组件交互用组件测试;
  • 路由、接口和关键用户旅程用端到端测试;
  • 视觉细节用浏览器人工检查或视觉回归。

不要用大量脆弱的像素或 DOM 层级断言替代用户可见行为。按钮是否可用、表单是否提交、错误是否显示,比第几个 div 更稳定。

处理不稳定测试

先重复运行并记录失败模式,再检查:

  • 共享全局状态是否清理;
  • 时间和时区是否固定;
  • 随机数是否设置种子;
  • 异步任务是否有明确完成信号;
  • 端口、文件、数据库是否隔离;
  • 测试顺序是否影响结果;
  • 外部服务是否应该替换为可控测试替身。

禁止只增加重试次数后宣告解决。重试可以缓解环境偶发问题,但必须保留可观测性。

测试数据与隐私

使用明确的虚构数据和占位符。不要把生产快照、真实账号、订单、日志或访问 Token 直接加入 fixture。需要真实形状时,先最小化字段并脱敏。

一份合格的测试报告

text
新增测试:
- [测试名]:防止 [具体回归]

修复前:
- [命令]:失败,原因是 [目标断言]

修复后:
- [单测命令]:通过
- [模块命令]:通过
- [构建命令]:通过

未运行:
- [端到端测试]:缺少 [环境]

风险:
- [尚未覆盖的场景]

完成门槛

  • [ ] 测试意图对应真实行为或业务规则。
  • [ ] 回归测试在修复前能因正确原因失败。
  • [ ] 没有通过过度 mock 隐藏目标问题。
  • [ ] 从最小测试扩大到合适的项目检查。
  • [ ] 测试数据不包含真实敏感信息。

下一步

界面任务继续学习 根据截图实现和迭代界面;大型结构调整进入 可回退的重构与迁移

参考

程序员小枫同学:用好新工具,练好工程内功,做出可靠交付。