- 开发前明确验收条件,开发中持续测试与审查,交付前验证最终代码。
- 测试通过只说明已检查的行为符合预期,不能保证代码没有缺陷。
- 验收 Agent 的工作,应核对实际运行的检查、结果和未验证的部分。
你让 Coding Agent 实现“满 100 元减 20 元”。它报告测试通过,页面却把 80 元订单算成了 60 元:只测 120 元时,“所有订单都减 20 元”的错误代码也能过关。
一次规范的开发,要把“需求中的正确结果”一直追踪到“最终代码的检查记录”。本文沿用优惠券案例,介绍 Coding Agent 应完成的验证流程;具体检查由项目规则和改动风险决定,借助 Superpowers 等 skill 时,再落实相应的执行要求。
一、完整验证流程
沿着这条优惠券需求向下看:每一步都留下结果,下一步再据此检查。
一句需求,经过八步检查,才有可核对的交付证据。
- 需求与验收
先写清门槛与订单变化后的预期。
100 元应付 80 元;降到 80 元后撤销优惠 - 环境与基线
运行已有检查,记录开始时的问题。
留下修改前的通过与失败记录 - 验证方案
把验收条件对应到函数、接口和页面。
每个条件都有检查位置
- 开发中反馈
用局部测试推动实现,重构后再次运行。
采用 TDD:预期失败 → 实现 → 通过 → 重构 - 回归与工程检查
检查旧功能,运行项目要求的工程检查。
测试、静态检查、类型检查与构建各留结果 - 审查与修复
对照需求阅读实际代码,修复遗漏并复查。
测试没想到的问题,也要得到处理
- 最终验收
在交付版本上核对需求与必需检查。
结果对应最终代码及适用的 CI 任务 - 交付证据
交回命令、结果、环境和未检查的部分。
说明哪些已验证,哪些仍有缺口
发现问题就返回修复检查失败或审查发现遗漏时,回到对应步骤;修复后重新验证。
流程需要完整交代,测试项目则按需选择。只修改文案与修改支付逻辑,需要的检查不同;同一个项目也不必为每次改动新增所有层级的测试。
二、需求、基线与验证方案
先确定什么算正确,再让 Agent 写实现和测试。 “满 100 元减 20 元”至少包含以下验收条件:
- 未到门槛:80 元订单应付 80 元。
- 恰好到门槛:100 元订单应付 80 元。
- 超过门槛:120 元订单应付 100 元。
- 订单变化:原价从 120 元降到 80 元后,接口和页面都应更新为 80 元。
小数金额怎样处理、优惠能否叠加、非法金额如何拒绝,需要按真实需求另行明确。本文只用整数金额和单一优惠教学,不据此推断完整的支付规则。期望值应来自需求和独立核算,不能直接用被测函数算出“正确答案”。
-
读取约定
查看
AGENTS.md、相邻实现、现有测试,以及依赖与 CI 配置。产出项目实际使用的验证命令
-
建立基线
在可运行的环境中,执行项目规定的已有检查。
产出修改前的代码状态、命令与失败项
后续出现失败时,用这份记录判断是否由本次改动引入。
-
安排覆盖
把每条验收条件对应到合适的检查位置。
验收对象 检查方法 确认结果 优惠门槛 函数测试 优惠计算逻辑正确 请求与返回值 集成检查 接口传递的金额正确 页面金额更新 用户路径检查 订单变化后,页面显示正确 产出验收条件与检查方法的对应关系
基线有失败时,先确认原因并记录如何处理。不能把已有失败藏起来,也不能在没有依据时全部归为“环境问题”。
三、案例与断言
加选 80 元,观察错误如何暴露;再换一份代码,用 100 元检查优惠门槛。
教学函数 · 浏览器内实际计算
让错误代码暴露出来
加选 80 元,看错误如何暴露。
实验设置
当前代码
无条件减 20return amount - 20; 测试结果
只测 120 元时,错误代码也能通过。加选 80 元,看看结论会不会改变。
| 订单金额 | 期望 | 实际 | 结果 |
|---|---|---|---|
| 120 元 | 100 元 | 100 元 | 通过 |
教学计算:只处理整数金额,不含叠券、税费与舍入。
比较实际结果与期望的检查叫断言。测试通过只说明所选案例符合期望,关键是选出能暴露错误的数据。
四、修复与 TDD
TDD(测试驱动开发)先写能暴露问题的测试,再修改代码使其通过,最后整理结构并重跑。整理结构而不改变行为,叫“重构”。
沿用刚才的错误代码,依次完成修复与重构。留意:代码一变,上一轮测试结果就不能代表当前版本。
教学函数 · 浏览器内实际计算
让一次失败带着代码往前走
演练步骤
- 红 · 复现错误
- 绿 · 修复代码
- 重构 · 整理命名
补上 80 元和 100 元案例,先运行,复现未满门槛也减价的错误。
当前代码
修复前return amount - 20; 测试结果
先运行测试,检查实际金额是否符合期望。
| 订单金额 | 期望 | 实际 | 结果 |
|---|---|---|---|
| 80 元 | 80 元 | — | 待运行 |
| 100 元 | 80 元 | — | 待运行 |
| 120 元 | 100 元 | — | 待运行 |
运行记录
教学演练:只运行这三个函数案例。实际开发还需检查原有测试与受影响的系统路径。
失败不一定来自目标缺陷,先核对原因:
- 80 元订单期望应付 80,实际应付 60:复现了目标错误,接下来修门槛判断。
- 找不到框架、导入失败:测试尚未检查到业务行为,先恢复运行环境。
- 新测试直接通过:核对行为是否已存在,或测试是否根本没检查新增的功能。
TDD 与测试层级的区别
TDD 描述写代码的顺序;单元、接口、端到端描述观察系统的位置。可以先写函数测试,也可以先写更完整的行为测试。
手动点页面有价值,但未必留下可自动重跑的断言。TDD 也不是所有 Coding Agent 自动遵守的行为;采用哪种开发方式,应由项目约定明确。Superpowers 对新功能、缺陷修复和行为修改默认强调 TDD,具体执行要求见后文。
这里演练已有错误的修复。新功能则从描述尚未实现行为的测试开始;先确认它因该行为缺失而失败,而不是只在代码完成后看到一次通过。
五、函数、接口与页面
函数算对了,接口仍可能返回旧金额,页面也可能没有更新。不同测试的区别,在于从哪一层检查结果。
选择“接口返回旧金额”,比较单元测试与接口测试能看见什么。
教学模拟 · 固定案例,不运行真实代码
同一个错误,不同测试看见的东西
检查设置
固定检查 80 元订单,期望应付 80 元。
金额传递
错误发生在计算优惠的函数里。
- 计算函数60 元在这里检查金额
- 接口返回60 元未观察
- 页面可见60 元未观察
检查结果
发现:80 元订单应付 80 元,实际只收 60 元。
这次检查了什么
直接调用优惠计算函数,检查输入 80 时是否输出 80。
只覆盖这个函数的行为。
每次只换一个条件,观察检查位置与结果如何变化。“通过”只证明这次观察到的行为。
- 单元测试
- 直接检查计算函数,便于定位局部错误,看不到页面。
- 集成测试
- 检查多个部分的协作。本例通过接口检查请求、业务逻辑与返回值;也可检查与数据库等依赖的连接。
- 端到端测试(E2E)
- 从系统入口走完整的目标路径。本例在浏览器检查用户可见金额;其他系统的入口也可能是移动应用或命令行。
观察范围更大,也需要合适的输入:只用 120 元订单走浏览器流程,仍可能漏掉门槛错误。
测试金字塔与覆盖率的边界
“测试金字塔”用大量快速的小范围检查,配合适量集成与完整流程检查,安排成本和反馈速度;它不规定固定数量比例。参见 The Practical Test Pyramid 。
覆盖率只描述哪些代码被执行。 所有样本都超过 100 元时,“减 20”这一行会被覆盖,但“不满 100 不优惠”仍可能没被检查。
浏览器检查应关注用户可见结果,并尽量独立,避免一个测试留下的状态影响另一个。 Playwright 官方建议 也强调这两点。
六、探索、回归与失败处理
单个金额算对了,还要检查状态变化。例如,把已有订单从 120 元改为 80 元,优惠能否撤销、页面能否更新。
- ① 创建订单原价 120 元
页面应付 100 元 ✓ - ② 减少商品原价变成 80 元
优惠应当撤销 - ③ 观察更新接口返回 80 元
页面却还显示 100 元 ✕
人工探索
边操作边观察,寻找预先没想到的路径。发现旧金额问题,记下复现步骤。
回归测试
把“120 元改为 80 元后,页面应付 80 元”留成自动检查,以后的修改继续重跑。
回归测试检查改动有没有破坏已有行为,可以位于单元、集成或端到端层。它既包括保存 Bug 复现路径,也包括重跑原有功能的测试。人工探索补足预先写好的断言,不必把每次临时尝试都转成脚本。
开发中先跑相关的小范围测试,便于快速定位。完成前再运行项目要求的测试套件,不能把“这一个文件通过”报告成“全部测试通过”。套件太慢或受环境限制时,应说明未运行范围及替代检查,留下明确的验收缺口。
遇到失败,按证据处理:
- 本次回归:与基线对照,复现错误,修复代码,再重跑相关测试。
- 已有失败:记录名称与基线证据,说明对本次验收的影响,不能省略报告。
- 环境故障:依赖、服务或权限不足时,先恢复环境;没执行到行为断言,不等于行为验证失败或通过。
- 偶发失败:有时通过、有时失败时,保留日志、截图或追踪记录,调查状态共享、时序等原因;重试通过不能抹去第一次失败。
不能为了变绿而删除测试、跳过用例或放宽断言。如果需求确实改变,应先核对新标准,再同步更新实现和测试。
七、工程检查与专项验证
函数测试通过,只证明样本下的行为符合断言。代码能否满足工程约定、正确构建和实际使用,还需要不同的检查。
- 静态检查(lint)
- 按项目配置发现可疑写法和代码规范问题,不证明优惠业务算对。
- 类型检查
- 检查数据形状和调用是否匹配。例如金额字段缺失或传错类型;数字类型正确也可能算出错误金额。
- 编译与构建
- 确认代码和资源能生成目标产物。是否同时做类型检查取决于构建配置,不能默认包含。
- 运行与冒烟检查
- 启动应用,快速确认关键入口和主要路径能工作。冒烟是初步检查,不能代替详细验收。
类型检查在运行前发现一类错误,参见 TypeScript 官方说明 。不同检查的能力有交集,但通过一项不能推断其他项通过。命令以仓库实际配置为准,不能虚构一个不存在的测试脚本。
其他检查由改动风险触发:
- 页面与交互:核对桌面和手机布局、键盘访问、可访问名称、浏览器兼容;必要时做视觉对照。
- 权限与敏感数据:检查越权访问、非法输入、数据暴露,以及项目要求的安全扫描。
- 数据库与外部服务:检查数据迁移、旧数据兼容、接口契约(请求与返回格式的约定),以及超时、失败和恢复路径。
- 并发与性能:检查重复提交、竞争条件;有性能目标时再安排基准或负载测试。
- 部署与配置:在获准的目标环境确认启动、配置和关键路径;准备适用的迁移与回退验证。
例如,这次只修优惠显示,不必因此开展完整负载测试;如果改动会影响订单重复扣款,就应增加相应的并发与幂等检查。幂等指同一请求重复提交时,不重复产生扣款等效果。
测试本身的可信度
Agent 可能同时写错实现与测试。因此还要检查断言是否独立、测试是否真的触达目标行为。
- 独立期望:100 元应付 80 元来自规则,而不是调用优惠函数生成期望值。
- 真实行为:mock 是代替依赖的模拟对象。可以模拟外部支付服务,但不能把优惠计算也替换成预设答案,再宣称计算正确。
- 有效执行:核对发现和执行了多少测试、是否有跳过项;零条测试或跑错文件不能叫验证通过。
- 隔离与清理:每条测试准备自己的订单数据,结束后清理;避免一个测试留下的缓存或状态影响另一个。
- 覆盖边界:百分之百代码覆盖率仍可能缺少有效断言。高风险逻辑可进一步用变异测试,故意改错运算或条件,检查测试能否抓住它。参见
Stryker 的变异测试说明 。
UI 自动检查也有边界。 Playwright 的可访问性测试文档 指出,自动扫描无法发现全部可访问性问题,仍需要人工评估。
八、审查与最终验收
测试检查已经写下的断言,审查还要寻找没有写进断言的问题。 如果 Agent 漏掉“订单变更后撤销优惠”,函数测试可能全绿,但需求仍未完成。
需求符合性
逐条对照验收条件,确认门槛、金额更新和异常处理有对应实现与证据,也没有添加未经要求的行为。
代码与测试质量
阅读实际差异,检查数据流、边界、维护成本,以及测试是否只验证模拟答案。实现者自查后,再按项目要求安排独立审查。
审查可以由人或另一个 Agent 执行。分配给多个 Agent 时,主 Agent 仍要核对实际代码差异和验证记录,不能只转述子 Agent 的“已完成”。
-
发现问题
记录未满足的需求,或定位具体代码缺陷。
产出留下可追踪的问题记录
-
修复与重跑
修改实现、补充必要测试,运行覆盖改动的检查。影响其他路径时,扩大回归范围。
产出得到修复后的检查结果
-
复查结果
核对问题是否解决、修复是否引入新问题。未解决项保留原因与影响。
产出确认解决情况与剩余限制
返回第 02 步,修复、重跑后再次复查。
记录剩余限制,进入最终版本验收。
核对最终版本
在准备交付的代码上完成规定检查,记录提交或工作区状态。
对新版本重跑受影响的检查;旧结果只代表旧版本。
CI(持续集成)是在代码提交或集成时自动构建、测试的流程,通常使用独立的运行环境。项目有 CI 时,要确认目标提交对应的必需任务已成功结束,而不是仍在排队、运行、跳过或被取消。本地通过不等于 CI 通过;CI 也只验证配置中实际运行的项目。参见 GitHub Actions 官方说明 。
合并冲突解决、依赖变更或目标分支更新使代码组合发生变化后,需要验证新的集成结果。只有任务包含发布时,才继续执行获准的部署与目标环境冒烟检查;本地开发验收本身不代表已上线。
九、Superpowers 的流程约束
Skill 把开发规则写成 Agent 可遵循的步骤。它约束先后顺序和完成门槛,具体使用 Vitest、Playwright 或其他工具,仍由项目决定。
以下以 Superpowers 6.4.2 的技能规则为例:
- 准备与规划确定起点与检查方法
- 开发循环用失败推动实现
- 审查循环检查需求与代码质量
- 审查实际改动
- 修复问题
- 重跑与复查
重大功能完成、合入主分支前等节点安排审查。
发现问题就返回修复;子代理模式还包含任务级审查和最终整体审查。
- 完成门槛先有证据,再做声明
- 运行最终检查
- 读取输出与退出码
- 报告验证结果
在最终代码上验证后再声称通过;本地合并后还要验证合并结果。
Skill 是执行约束,不是通过保证;仍需检查 Agent 是否真的执行。不同版本规则会变化,项目约定与用户明确要求也会影响流程。原始规则可查阅 Superpowers 技能目录 ,其中
完成前验证 直接说明了“先有证据,再做声明”的要求。
十、交付记录与验收
Agent 说“修好了,测试全部通过”,你还需要知道:跑了什么,结果怎样?
这次改了优惠计算和页面更新。依次补充功能记录与最终验收记录,观察哪些结论有证据支持。
虚构教学报告 · 命令与数量均为示例
功能证据与最终验收
本次改动
修复优惠计算,并让页面金额随订单更新。项目还要求构建、需求审查和最终版本回归。
Agent 的回复
“已经修好了,测试全部通过,可以交付。”
这些记录说明什么
缺少实际命令与运行结果,无法核对这句回复。
记录 A · 计算与原有测试
- 修复前
- 80 元订单应付 80 元,实际算出 60 元。
- 修复后
npm run test:unit18 / 18 通过,包含原有测试- 案例
- 80 → 80 元
- 100 → 80 元
- 120 → 100 元
记录 B · 接口与页面
- 接口
npm run test:api80、100、120 元订单分别返回 80、80、100 元。- 页面
npm run test:e2e三种金额显示正确;订单从 120 元改为 80 元后,页面也更新为 80 元。
记录 C · 最终版本验收
- 版本
- 教学版本 coupon-v3,包含页面修复;以下检查均在该版本完成,此后没有修改。
- 基线
- 修改前已有测试通过,新增案例复现了优惠错误。
- 构建
npm run build退出码 0。项目未单独配置 lint 和类型检查,不能声称它们已通过。- 审查
- 已对照三种金额及订单更新逐项检查实际差异;页面更新问题修复后已复查。
- 回归
- 最终版本重新运行 A、B 中的检查,执行数量符合预期,零失败、零跳过。
- 环境
- 本地测试环境;本例未配置 CI,也不包含部署和真实支付验收。
虚构记录,仅覆盖本例列出的验收条件。未检查生产支付、叠券和小数舍入;实际任务需要按风险另行安排。
功能检查有记录后,还要核对需求、工程检查和最终版本。组件中的“满足”只针对这个教学例子列出的验收条件,不代表所有生产风险已经排除。
可以直接发给 Agent 的要求
请按本次改动的验收条件,交回以下记录:
- 范围与基线:实现了哪些需求,修改前已有检查是什么状态,有哪些已知失败。
- 测试与工程检查:实际运行的完整命令、退出结果、执行与跳过数量,以及测试套件、类型检查和构建的结果。未配置的检查明确注明。
- 行为证据:80、100、120 元各算出多少,订单从 120 元改为 80 元后接口与页面如何变化;采用 TDD 时附正确失败与通过的记录。
- 审查结果:需求是否逐项满足,发现的问题如何处理,有无未解决项。
- 版本与环境:记录对应哪个提交或工作区状态,在哪个环境运行,是否验证最终改动及适用的 CI/合并结果。
- 限制与缺口:哪些检查失败、受阻、跳过或未做,原因和影响是什么,还有哪些条件未覆盖。
命令和数量应来自真实输出。“未运行”“已有失败”“部分通过”都应如实报告,不能统一改写成“全部通过”。
回看这次优惠需求:先确定金额规则与页面变化,建立基线,再用不同范围的检查获得反馈,经过回归、工程检查和审查,最后把证据绑定到交付版本。规范开发的验收,是确认这条链路成立,并清楚保留尚未验证的边界。