AI 编程
AI 编程

Coding Agent 的测试与验证

2026年9月30日 约 4,000 字 约 14 分钟阅读

你让 Coding Agent 实现“满 100 元减 20 元”。它报告测试通过,页面却把 80 元订单算成了 60 元:只测 120 元时,“所有订单都减 20 元”的错误代码也能过关。

一次规范的开发,要把“需求中的正确结果”一直追踪到“最终代码的检查记录”。本文沿用优惠券案例,介绍 Coding Agent 应完成的验证流程;具体检查由项目规则和改动风险决定,借助 Superpowers 等 skill 时,再落实相应的执行要求。

一、完整验证流程

沿着这条优惠券需求向下看:每一步都留下结果,下一步再据此检查。

贯穿案例满 100 元减 20 元

一句需求,经过八步检查,才有可核对的交付证据。

开发前确定检查什么
  1. 需求与验收

    先写清门槛与订单变化后的预期。

    100 元应付 80 元;降到 80 元后撤销优惠
  2. 环境与基线

    运行已有检查,记录开始时的问题。

    留下修改前的通过与失败记录
  3. 验证方案

    把验收条件对应到函数、接口和页面。

    每个条件都有检查位置
开发中获得反馈并修正
  1. 开发中反馈

    用局部测试推动实现,重构后再次运行。

    采用 TDD:预期失败 → 实现 → 通过 → 重构
  2. 回归与工程检查

    检查旧功能,运行项目要求的工程检查。

    测试、静态检查、类型检查与构建各留结果
  3. 审查与修复

    对照需求阅读实际代码,修复遗漏并复查。

    测试没想到的问题,也要得到处理
交付前核对证据与边界
  1. 最终验收

    在交付版本上核对需求与必需检查。

    结果对应最终代码及适用的 CI 任务
  2. 交付证据

    交回命令、结果、环境和未检查的部分。

    说明哪些已验证,哪些仍有缺口

发现问题就返回修复检查失败或审查发现遗漏时,回到对应步骤;修复后重新验证。

流程需要完整交代,测试项目则按需选择。只修改文案与修改支付逻辑,需要的检查不同;同一个项目也不必为每次改动新增所有层级的测试。

二、需求、基线与验证方案

先确定什么算正确,再让 Agent 写实现和测试。 “满 100 元减 20 元”至少包含以下验收条件:

  • 未到门槛:80 元订单应付 80 元。
  • 恰好到门槛:100 元订单应付 80 元。
  • 超过门槛:120 元订单应付 100 元。
  • 订单变化:原价从 120 元降到 80 元后,接口和页面都应更新为 80 元。

小数金额怎样处理、优惠能否叠加、非法金额如何拒绝,需要按真实需求另行明确。本文只用整数金额和单一优惠教学,不据此推断完整的支付规则。期望值应来自需求和独立核算,不能直接用被测函数算出“正确答案”。

开始修改前
  1. 读取约定

    查看 AGENTS.md、相邻实现、现有测试,以及依赖与 CI 配置。

    产出项目实际使用的验证命令

  2. 建立基线

    在可运行的环境中,执行项目规定的已有检查。

    产出修改前的代码状态、命令与失败项

    后续出现失败时,用这份记录判断是否由本次改动引入。

  3. 安排覆盖

    把每条验收条件对应到合适的检查位置。

    验收对象检查方法确认结果
    优惠门槛函数测试优惠计算逻辑正确
    请求与返回值集成检查接口传递的金额正确
    页面金额更新用户路径检查订单变化后,页面显示正确

    产出验收条件与检查方法的对应关系

基线有失败时,先确认原因并记录如何处理。不能把已有失败藏起来,也不能在没有依据时全部归为“环境问题”。

三、案例与断言

加选 80 元,观察错误如何暴露;再换一份代码,用 100 元检查优惠门槛。

01

教学函数 · 浏览器内实际计算

让错误代码暴露出来

优惠规则满 100 元减 20 元

加选 80 元,看错误如何暴露。

当前代码

无条件减 20
return amount - 20;

测试结果

1 / 1 通过

只测 120 元时,错误代码也能通过。加选 80 元,看看结论会不会改变。

订单金额期望实际结果
120 元100 元100 元通过

教学计算:只处理整数金额,不含叠券、税费与舍入。

比较实际结果与期望的检查叫断言。测试通过只说明所选案例符合期望,关键是选出能暴露错误的数据。

四、修复与 TDD

TDD(测试驱动开发)先写能暴露问题的测试,再修改代码使其通过,最后整理结构并重跑。整理结构而不改变行为,叫“重构”。

沿用刚才的错误代码,依次完成修复与重构。留意:代码一变,上一轮测试结果就不能代表当前版本。

02

教学函数 · 浏览器内实际计算

让一次失败带着代码往前走

当前代码

修复前
return amount - 20;

测试结果

尚未运行

先运行测试,检查实际金额是否符合期望。

测试案例 · 期望值保持不变
订单金额期望实际结果
80 元80 元—待运行
100 元80 元—待运行
120 元100 元—待运行

教学演练:只运行这三个函数案例。实际开发还需检查原有测试与受影响的系统路径。

失败不一定来自目标缺陷,先核对原因:

  • 80 元订单期望应付 80,实际应付 60:复现了目标错误,接下来修门槛判断。
  • 找不到框架、导入失败:测试尚未检查到业务行为,先恢复运行环境。
  • 新测试直接通过:核对行为是否已存在,或测试是否根本没检查新增的功能。
TDD 与测试层级的区别

TDD 描述写代码的顺序;单元、接口、端到端描述观察系统的位置。可以先写函数测试,也可以先写更完整的行为测试。

手动点页面有价值,但未必留下可自动重跑的断言。TDD 也不是所有 Coding Agent 自动遵守的行为;采用哪种开发方式,应由项目约定明确。Superpowers 对新功能、缺陷修复和行为修改默认强调 TDD,具体执行要求见后文。

这里演练已有错误的修复。新功能则从描述尚未实现行为的测试开始;先确认它因该行为缺失而失败,而不是只在代码完成后看到一次通过。

五、函数、接口与页面

函数算对了,接口仍可能返回旧金额,页面也可能没有更新。不同测试的区别,在于从哪一层检查结果。

选择“接口返回旧金额”,比较单元测试与接口测试能看见什么。

03

教学模拟 · 固定案例,不运行真实代码

同一个错误,不同测试看见的东西

金额传递

错误发生在计算优惠的函数里。

  1. 计算函数60 元在这里检查金额
  2. 接口返回60 元未观察
  3. 页面可见60 元未观察

检查结果

发现错误

发现:80 元订单应付 80 元,实际只收 60 元。

这次检查了什么

直接调用优惠计算函数,检查输入 80 时是否输出 80。

只覆盖这个函数的行为。

每次只换一个条件,观察检查位置与结果如何变化。“通过”只证明这次观察到的行为。

单元测试
直接检查计算函数,便于定位局部错误,看不到页面。
集成测试
检查多个部分的协作。本例通过接口检查请求、业务逻辑与返回值;也可检查与数据库等依赖的连接。
端到端测试(E2E)
从系统入口走完整的目标路径。本例在浏览器检查用户可见金额;其他系统的入口也可能是移动应用或命令行。

观察范围更大,也需要合适的输入:只用 120 元订单走浏览器流程,仍可能漏掉门槛错误。

测试金字塔与覆盖率的边界

“测试金字塔”用大量快速的小范围检查,配合适量集成与完整流程检查,安排成本和反馈速度;它不规定固定数量比例。参见 The Practical Test Pyramid 。

覆盖率只描述哪些代码被执行。 所有样本都超过 100 元时,“减 20”这一行会被覆盖,但“不满 100 不优惠”仍可能没被检查。

浏览器检查应关注用户可见结果,并尽量独立,避免一个测试留下的状态影响另一个。 Playwright 官方建议 也强调这两点。

六、探索、回归与失败处理

单个金额算对了,还要检查状态变化。例如,把已有订单从 120 元改为 80 元,优惠能否撤销、页面能否更新。

  1. ① 创建订单原价 120 元
    页面应付 100 元 ✓
  2. ② 减少商品原价变成 80 元
    优惠应当撤销
  3. ③ 观察更新接口返回 80 元
    页面却还显示 100 元 ✕
虚构缺陷:页面未随订单更新。输入值正确之外,还要检查从旧状态到新状态的变化。
  • 人工探索

    边操作边观察,寻找预先没想到的路径。发现旧金额问题,记下复现步骤。

  • 回归测试

    把“120 元改为 80 元后,页面应付 80 元”留成自动检查,以后的修改继续重跑。

回归测试检查改动有没有破坏已有行为,可以位于单元、集成或端到端层。它既包括保存 Bug 复现路径,也包括重跑原有功能的测试。人工探索补足预先写好的断言,不必把每次临时尝试都转成脚本。

开发中先跑相关的小范围测试,便于快速定位。完成前再运行项目要求的测试套件,不能把“这一个文件通过”报告成“全部测试通过”。套件太慢或受环境限制时,应说明未运行范围及替代检查,留下明确的验收缺口。

遇到失败,按证据处理:

  • 本次回归:与基线对照,复现错误,修复代码,再重跑相关测试。
  • 已有失败:记录名称与基线证据,说明对本次验收的影响,不能省略报告。
  • 环境故障:依赖、服务或权限不足时,先恢复环境;没执行到行为断言,不等于行为验证失败或通过。
  • 偶发失败:有时通过、有时失败时,保留日志、截图或追踪记录,调查状态共享、时序等原因;重试通过不能抹去第一次失败。

不能为了变绿而删除测试、跳过用例或放宽断言。如果需求确实改变,应先核对新标准,再同步更新实现和测试。

七、工程检查与专项验证

函数测试通过,只证明样本下的行为符合断言。代码能否满足工程约定、正确构建和实际使用,还需要不同的检查。

静态检查(lint)
按项目配置发现可疑写法和代码规范问题,不证明优惠业务算对。
类型检查
检查数据形状和调用是否匹配。例如金额字段缺失或传错类型;数字类型正确也可能算出错误金额。
编译与构建
确认代码和资源能生成目标产物。是否同时做类型检查取决于构建配置,不能默认包含。
运行与冒烟检查
启动应用,快速确认关键入口和主要路径能工作。冒烟是初步检查,不能代替详细验收。

类型检查在运行前发现一类错误,参见 TypeScript 官方说明 。不同检查的能力有交集,但通过一项不能推断其他项通过。命令以仓库实际配置为准,不能虚构一个不存在的测试脚本。

其他检查由改动风险触发:

  • 页面与交互:核对桌面和手机布局、键盘访问、可访问名称、浏览器兼容;必要时做视觉对照。
  • 权限与敏感数据:检查越权访问、非法输入、数据暴露,以及项目要求的安全扫描。
  • 数据库与外部服务:检查数据迁移、旧数据兼容、接口契约(请求与返回格式的约定),以及超时、失败和恢复路径。
  • 并发与性能:检查重复提交、竞争条件;有性能目标时再安排基准或负载测试。
  • 部署与配置:在获准的目标环境确认启动、配置和关键路径;准备适用的迁移与回退验证。

例如,这次只修优惠显示,不必因此开展完整负载测试;如果改动会影响订单重复扣款,就应增加相应的并发与幂等检查。幂等指同一请求重复提交时,不重复产生扣款等效果。

测试本身的可信度

Agent 可能同时写错实现与测试。因此还要检查断言是否独立、测试是否真的触达目标行为。

  • 独立期望:100 元应付 80 元来自规则,而不是调用优惠函数生成期望值。
  • 真实行为:mock 是代替依赖的模拟对象。可以模拟外部支付服务,但不能把优惠计算也替换成预设答案,再宣称计算正确。
  • 有效执行:核对发现和执行了多少测试、是否有跳过项;零条测试或跑错文件不能叫验证通过。
  • 隔离与清理:每条测试准备自己的订单数据,结束后清理;避免一个测试留下的缓存或状态影响另一个。
  • 覆盖边界:百分之百代码覆盖率仍可能缺少有效断言。高风险逻辑可进一步用变异测试,故意改错运算或条件,检查测试能否抓住它。参见 Stryker 的变异测试说明 。

UI 自动检查也有边界。 Playwright 的可访问性测试文档 指出,自动扫描无法发现全部可访问性问题,仍需要人工评估。

八、审查与最终验收

测试检查已经写下的断言,审查还要寻找没有写进断言的问题。 如果 Agent 漏掉“订单变更后撤销优惠”,函数测试可能全绿,但需求仍未完成。

  • 需求符合性

    逐条对照验收条件,确认门槛、金额更新和异常处理有对应实现与证据,也没有添加未经要求的行为。

  • 代码与测试质量

    阅读实际差异,检查数据流、边界、维护成本,以及测试是否只验证模拟答案。实现者自查后,再按项目要求安排独立审查。

审查可以由人或另一个 Agent 执行。分配给多个 Agent 时,主 Agent 仍要核对实际代码差异和验证记录,不能只转述子 Agent 的“已完成”。

审查与修复
  1. 发现问题

    记录未满足的需求,或定位具体代码缺陷。

    产出留下可追踪的问题记录

  2. 修复与重跑

    修改实现、补充必要测试,运行覆盖改动的检查。影响其他路径时,扩大回归范围。

    产出得到修复后的检查结果

  3. 复查结果

    核对问题是否解决、修复是否引入新问题。未解决项保留原因与影响。

    产出确认解决情况与剩余限制

仍有待修复问题

返回第 02 步,修复、重跑后再次复查。

审查问题已处理

记录剩余限制,进入最终版本验收。

核对最终版本

在准备交付的代码上完成规定检查,记录提交或工作区状态。

代码再变,重新验证

对新版本重跑受影响的检查;旧结果只代表旧版本。

CI(持续集成)是在代码提交或集成时自动构建、测试的流程,通常使用独立的运行环境。项目有 CI 时,要确认目标提交对应的必需任务已成功结束,而不是仍在排队、运行、跳过或被取消。本地通过不等于 CI 通过;CI 也只验证配置中实际运行的项目。参见 GitHub Actions 官方说明 。

合并冲突解决、依赖变更或目标分支更新使代码组合发生变化后,需要验证新的集成结果。只有任务包含发布时,才继续执行获准的部署与目标环境冒烟检查;本地开发验收本身不代表已上线。

九、Superpowers 的流程约束

Skill 把开发规则写成 Agent 可遵循的步骤。它约束先后顺序和完成门槛,具体使用 Vitest、Playwright 或其他工具,仍由项目决定。

以下以 Superpowers 6.4.2 的技能规则为例:

  1. 准备与规划确定起点与检查方法
    1. 运行已有测试
    2. 记录基线
    3. 拆分验证步骤

    基线记录,以及含测试、命令和预期结果的任务计划。

  2. 开发循环用失败推动实现
    1. 预期失败
    2. 最小实现
    3. 通过
    4. 重构后重跑

    先确认失败原因正确,再实现;完成前检查项目测试套件。

    新增行为时,从新的失败测试开始。

  3. 审查循环检查需求与代码质量
    1. 审查实际改动
    2. 修复问题
    3. 重跑与复查

    重大功能完成、合入主分支前等节点安排审查。

    发现问题就返回修复;子代理模式还包含任务级审查和最终整体审查。

  4. 完成门槛先有证据,再做声明
    1. 运行最终检查
    2. 读取输出与退出码
    3. 报告验证结果

    在最终代码上验证后再声称通过;本地合并后还要验证合并结果。

Skill 是执行约束,不是通过保证;仍需检查 Agent 是否真的执行。不同版本规则会变化,项目约定与用户明确要求也会影响流程。原始规则可查阅 Superpowers 技能目录 ,其中 完成前验证 直接说明了“先有证据,再做声明”的要求。

十、交付记录与验收

Agent 说“修好了,测试全部通过”,你还需要知道:跑了什么,结果怎样?

这次改了优惠计算和页面更新。依次补充功能记录与最终验收记录,观察哪些结论有证据支持。

04

虚构教学报告 · 命令与数量均为示例

功能证据与最终验收

Agent 的回复

“已经修好了,测试全部通过,可以交付。”

这些记录说明什么

还不能确认修好

缺少实际命令与运行结果,无法核对这句回复。

虚构记录,仅覆盖本例列出的验收条件。未检查生产支付、叠券和小数舍入;实际任务需要按风险另行安排。

功能检查有记录后,还要核对需求、工程检查和最终版本。组件中的“满足”只针对这个教学例子列出的验收条件,不代表所有生产风险已经排除。

可以直接发给 Agent 的要求

请按本次改动的验收条件,交回以下记录:

  1. 范围与基线:实现了哪些需求,修改前已有检查是什么状态,有哪些已知失败。
  2. 测试与工程检查:实际运行的完整命令、退出结果、执行与跳过数量,以及测试套件、类型检查和构建的结果。未配置的检查明确注明。
  3. 行为证据:80、100、120 元各算出多少,订单从 120 元改为 80 元后接口与页面如何变化;采用 TDD 时附正确失败与通过的记录。
  4. 审查结果:需求是否逐项满足,发现的问题如何处理,有无未解决项。
  5. 版本与环境:记录对应哪个提交或工作区状态,在哪个环境运行,是否验证最终改动及适用的 CI/合并结果。
  6. 限制与缺口:哪些检查失败、受阻、跳过或未做,原因和影响是什么,还有哪些条件未覆盖。

命令和数量应来自真实输出。“未运行”“已有失败”“部分通过”都应如实报告,不能统一改写成“全部通过”。

回看这次优惠需求:先确定金额规则与页面变化,建立基线,再用不同范围的检查获得反馈,经过回归、工程检查和审查,最后把证据绑定到交付版本。规范开发的验收,是确认这条链路成立,并清楚保留尚未验证的边界。