#Vibe Coding#AI Agent#TypeScript#开源

Vibe Coding 特征测试:重构前先锁定遗留行为

遗留代码没有规格时,AI 很容易把“不好看”误判为“应当修正”。本文用基线样本、可观察边界和差异审批建立特征测试,让重构先证明行为未被偷偷改写。

本文要点

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

接手遗留模块时,最危险的提示不是“请修复一个明确缺陷”,而是“把这段旧代码整理干净”。AI 会自然地统一空值、调整排序、改写错误信息、合并分支;这些变化在代码审阅里很像改进,却可能破坏调用方依赖多年的实际行为。没有可信规格时,第一步不能让模型定义“正确”,而要先回答:当前版本面对哪些输入,外部究竟能观察到什么?

特征测试就是为这个阶段服务的临时规格。它记录现有系统的可观察行为,不预先声称这些行为都合理。它与普通回归测试的区别在于来源:普通测试通常从需求推导期望;特征测试先从冻结版本采样,再由人决定哪些结果应保留、哪些是待修缺陷。整体重构策略可参考AI 代码重构,但每条护栏仍要绑定本次模块和基线提交。

先圈定观察面,而不是给内部实现拍照

先画出模块边界:公开函数、HTTP 响应、写入记录、发出的事件、文件输出和明确的错误类型。私有函数调用次数、临时变量名、SQL 语句文本通常不是契约,把它们写进断言只会让重构无法移动。可先借助编程 Agent 的仓库地图追踪入口和消费者,再列出“输入、环境、输出、副作用”四列。

例如旧价格函数的观察表可以包含:普通订单、空购物车、折扣刚好达到门槛、未知优惠码、重复行项目和极大整数。对每个样本记录返回金额、错误类别和库存预留次数;不要只保存一个巨大对象快照。巨大快照混合了时间戳、字段顺序和业务结果,reviewer 很难判断一行变化是否重要。Jest 官方快照文档也强调快照应被审阅并保持聚焦;它不是绕过显式断言的许可。

采样前冻结 BASE_SHA、锁文件、运行时版本、locale、时区、随机种子以及使用的 fixture 哈希。工作树若不干净,必须先保存状态清单,不能把未提交改动生成的输出冒充发布基线。Git diff 用于确认测试引入阶段没有顺手修改生产代码:

bash
git rev-parse HEAD
git status --short
git diff -- src/legacy tests/legacy
pnpm test -- legacy-price

这些命令名称只是示例,实际任务应使用仓库已有脚本。测试第一次在原实现上必须稳定通过;如果同一输入连续运行得到不同输出,先找时间、随机、并发或外部依赖,不要挑一次结果写成 golden file。

用小样本表达行为类别

让 AI 生成初始样本时,输入不是“多写点测试”,而是行为清单和观察边界。每个案例标记来源:生产脱敏样本、历史缺陷、调用方契约、边界分析或人工构造。参数化测试可以减少重复,但案例名要写清触发条件和现有结果:

ts
test.each([
  { name: "空购物车", input: [], total: 0, code: undefined },
  { name: "未知优惠码", input: baseCart, total: 1200, code: "IGNORED" },
])("$name 保持基线行为", ({ input, total, code }) => {
  const result = price(input);
  expect(result.total).toBe(total);
  expect(result.warningCode).toBe(code);
});

示例里的值必须来自真实基线运行,而不是模型猜测。对 JSON 或 HTML 这类大输出,先规范化不相关字段,再对关键片段做显式断言;规范化器本身也要有小测试。删除时间戳可以,删除错误码不行。更广的输入空间可交给AI 生成代码的属性测试,但属性不应取代已知业务样本。

把“当前如此”和“应该如此”分开

每条特征测试附一个处置标签:preserve 表示重构不可改变,suspected-bug 表示暂时记录但需要产品决策,incidental 表示可在当前改动中忽略。比如接口把缺失昵称输出为空字符串,调用方可能依赖它;即使团队更偏好 null,也不能由 AI 在重构中自行选择。先锁住空字符串,再用独立缺陷任务迁移消费者。

当 reviewer 批准改变行为时,不是直接更新快照。提交应同时展示旧结果、新需求依据、受影响消费者、迁移或兼容安排以及新增的正反例。旧特征测试可以改成明确的需求测试,提交信息解释为什么期望变化。这样测试历史记录的是决策,不是“为了让 CI 变绿而接受新输出”。编程 Agent 的改动验证门可用于把基线、diff 与测试证据绑定到同一 HEAD。

防止护栏变成遗留负担

特征测试完成使命后要整理。重构稳定且行为得到确认时,将关键案例提升为长期回归测试;仅用于过渡的内部快照删除;suspected-bug 必须进入明确工单,不能永久悬空。测试若失败,先分类为预期行为变更、意外回归、环境漂移或断言过度绑定,再决定修实现还是修测试。AI 测试生成可以铺案例,但分类与接受期望仍由人负责。

一次可信交付至少留下五项证据:冻结基线、行为样本来源、原实现通过结果、重构后同一集合通过结果、所有期望差异的批准记录。它不证明遗留行为本身正确,只证明团队知道改动前后发生了什么。在 Vibe Coding 中,这个区分很关键:模型可以快速重写代码,特征测试让“保持什么”不再由模型的审美决定。

延伸阅读

Related

相关推荐