#Vibe Coding#AI Agent#TypeScript#开源

Vibe Coding 测试预言审查:断言为什么能证明结果正确

测试执行了路径,不等于它能识别错误。本文从需求依据、预言独立性、可观察结果和故障校准四方面审查 AI 生成断言,避免实现与测试一起自证。

本文要点

  • 主题聚焦:Vibe Coding、AI Agent、TypeScript、开源
  • 适合人群:独立开发者、全栈工程师、AI 应用开发者
  • 核心价值:快速理解背景、实践路径、常见误区和工程建议
作者 @admin·发布于 2026年7月30日·更新于 2026年7月30日

测试可以运行得很勤快,却什么也没证明。AI 最常见的做法是读取实现后生成测试,再用同一段算法计算 expected:生产代码把税率乘错,测试里的复制品也乘错,于是两个结果相等。另一种假绿是只断言“没有抛异常”“数组长度大于零”或“mock 被调用”,真正的金额、权限与持久化状态都没有被检查。

测试预言是判断一次执行是否正确的机制。它可以是具体期望值、业务不变量、参考实现、前后关系、协议约束或人工批准的基准。Vibe Coding 中,生成用例很便宜,预言却仍然昂贵,因为它需要独立于当前实现的正确性依据。AI 测试生成负责扩展案例时,也不能替 reviewer 决定“为什么这个结果算对”。

每个断言先回答来源

审查时给关键断言标注来源,而不是只看 matcher 是否漂亮。可接受来源包括:明确验收条件、公开协议规范、业务规则表、已批准的历史样本、独立参考实现、数据守恒等不变量。来源为“当前函数返回了这个值”只能形成特征测试,不能证明期望正确;应按Vibe Coding 特征测试的方式标记当前行为与目标行为。

以优惠金额为例,下面的断言看起来精确,实际仍然循环依赖:

ts
const expected = calculateDiscount(copyOfRules, cart);
expect(calculateDiscount(rules, cart)).toBe(expected);

若 copyOfRules 是从生产实现复制并稍作改名,两个错误会同步。更可信的做法是从一条可手算规则得到固定样本,或使用结构不同的简洁参考模型;再补充“不超过小计、金额不为负、添加无折扣商品不会降低应付额”等不变量。具体值讲业务故事,不变量覆盖更广输入,两者职责不同。

选择能观察业务结果的层

预言太弱会漏错,太靠内部又会阻碍重构。发送邮件的用例如果只检查 send() 被调用,无法证明收件人、模板版本与幂等键正确;如果断言内部 helper 的每次调用顺序,又可能把无关实现固化。观察边界应落在消费者能感知的位置:返回值、状态迁移、持久化结果、对外请求、授权拒绝和可恢复错误。

为每个高风险结果至少安排一个正向和一个反向预言。权限测试既证明 owner 可读,也证明非 owner 不可读且没有泄漏数据;幂等测试既证明第一次成功,也证明相同键重放不产生第二个副作用;删除测试既看响应,也核对数据与关联资源的最终状态。场景如何系统排列可参考Vibe Coding 测试矩阵。

Jest 的 toEqual、toMatchObject、异常和异步 matcher 只是表达工具。选择 matcher 时保留契约字段,排除真正不稳定且无业务意义的字段。expect.any(String) 用于随机 ID 尚可,用于错误码就过宽;整个对象 snapshot 便于发现未知差异,却需要 reviewer 逐行确认,不能自动更新。

按问题选择预言类型

确定性纯函数适合具体示例和独立参考模型。解析与序列化适合往返关系,例如 decode(encode(x)) 保持规范化后的 x。排序适合有序性与元素多重集不变。状态机适合允许/禁止转换与副作用上限。外部协议适合 schema、状态码、错误语义和跨版本契约。模型输出等非确定结果,则适合结构约束、必须包含/禁止包含的事实、评测集与人工抽样,不能硬断言完整字符串。

属性测试框架可以批量生成输入,但属性本身仍是预言。fast-check 官方文档将 property 与 arbitrary 分开,正好提醒团队:生成域回答“测什么输入”,property 回答“什么必须成立”。若两者都由 AI 从同一个实现推断,独立性问题仍未解决。

对时间、随机、并发和外部服务,先决定哪些变量应固定,哪些需要真实观察。注入时钟能使到期规则可断言;固定随机种子使失败可重放;对第三方 API 使用经过契约验证的替身,同时保留少量真实集成测试。不要把 sleep(100) 后“暂时没看到错误”当作并发正确性的预言。

用已知坏实现校准辨错能力

预言审查不能止于阅读。选择与风险对应的小型故障:把 > 改成 >=、删除权限判断、交换两个状态、重复副作用、吞掉异常。若测试仍绿,说明预言、输入或执行路径至少一项不足。系统化做法是AI 生成补丁的变异测试,但人工注入少量关键错误也能验证门禁是否有牙齿。

幸存故障要分类。可能是断言缺失、输入没触发、变异等价、行为不可观察,或需求本身不明确。不得简单增加覆盖率目标,因为覆盖只能说明代码被执行;也不得让 AI 根据幸存变异放宽预言。高风险故障无法被杀死时,测试集合不能作为合并证据。

形成可审计的预言清单

每篇测试变更附一张短表:风险、用例 ID、观察结果、预言类型、依据、故障校准和剩余未知。reviewer 优先审查金额、权限、数据删除、迁移和跨服务副作用,而不是平均分配注意力。AI Code Review 实践中的定位与分级方法同样适用于测试代码。

当需求改变,先更新依据,再更新预言;当实现重构,预言原则上不变;当外部协议升级,基线与兼容窗口一起版本化。测试失败后,只有证据证明旧期望已经失效,才修改断言。最终完成标准不是“AI 写了很多 expect”,而是每个关键 expect 都能解释来源、能在错误实现上变红,并且观察的是用户或消费者真正关心的结果。

延伸阅读

Related

相关推荐