返回文章列表工程实践

AI 写代码更快了,为什么上线还在等测试?

先拆开 CI 的排队、执行与重试,再用可下载的离线练习选择测试、保守回退,并通过全量对照发现被漏掉的失败。

8 分钟阅读
本页内容8 个章节

代码写完了,上线却没有变快

一个小团队正在做发票功能。AI 很快完成了代码,可合并请求还在等执行机器、重跑偶尔失败的检查,再把无关测试全部跑一遍。这里说的 CI(持续集成),就是每次代码变更后自动运行构建与测试的流程。写代码更快,只是让等待出现在另一个地方;交付前该做的检查并没有消失。

Anthropic 在 9 月 14 日的文章中介绍了自己的确定性测试选择服务:收集测试结果的组件落后,导致选择器依据过时的历史记录决策。后来它们把状态从工作进程中拆出,让服务可以扩展。这给我们的启发是维护好决策依据,而不是让模型凭感觉删除测试。

下面做一个更小的原创练习:看三条虚构耗时记录,为两个简单模块选择测试,再用全量运行检查选择是否漏掉失败。建议在团队已有可重复任务和明确测试命令后做这一步。如果最慢的是等机器,优先做复杂的测试选择器未必划算。

打开一个可以完整看懂的小项目

下载并解压原创练习包,只需 Node.js 20 或更新版本,不用安装依赖或调用 API。目录里有发票、通知两个模块,两个业务测试文件与一个冒烟测试文件,一份手写映射、耗时数据,以及几个分析脚本。业务数据和耗时记录都是合成的。

在 Onevium 左侧“项目”旁点击“添加项目”,选择“打开已有文件夹”,选中 ci-test-selection-starter。从该项目行新建会话。会话顶部的“浏览全部文件”可以查看文件,终端图标打开内置终端。运行前先核对目录,复用的终端可能还停在之前的位置;也可以直接用你平时的终端。

先运行下面六组练习自检、两个业务测试和一个冒烟检查。第一条测试命令检查选择规则与算术,第二条实际运行虚构业务代码。解压目录不是 Git 仓库也能浏览文件;这两条命令都不是模型评测,也不代表 Onevium 完整工作流已经实测。

在解压后的 ci-test-selection-starter 目录运行
node --version
node --test fixture.test.mjs
node --test tests/invoice.test.mjs tests/notification.test.mjs tests/smoke.test.mjs

先看时间花在哪,不急着少跑测试

运行 node analyze.mjs,结果会拆开首次排队、首次执行、额外重试。这组简化记录的三段时间互不重叠,重试包含第一次尝试之后新增的等待和执行。三次合计排队 9 分钟、执行 15 分钟、重试 2 分钟,共 26 分钟;这是多次运行的累计,不是一次上线的等待时间。

DEMO-B 总共 12 分钟,其中首次排队就占了 6 分钟;DEMO-C 的 9 分钟里有 8 分钟在执行。前者值得调查执行机器和并发限制,后者才适合继续拆解慢测试。看到重试记录,也应先查第一次为何失败,再决定是否增加自动重试。

换成自己的 CI 时,使用真实时间戳,把取消与未完成运行另列。多个任务并行时,耗时会重叠,不能把各任务时长相加当成整次交付时长。先用同一口径比较几次相近变更,不把这里的虚构数字当作节省时间的证据。

虚构的串行流水线记录,单位:分钟
运行排队首次执行额外重试合计
DEMO-A2305
DEMO-B64212
DEMO-C1809
窄屏可左右滑动查看完整表格。
读取包内耗时记录
node analyze.mjs

让每一个测试选择都有依据

打开 dependency-map.json:src/invoice.mjs 对应发票测试,src/notification.mjs 对应通知测试;每次还会固定保留一个检查入口能否加载的冒烟测试。这个很小的检查不能代替业务断言。

下面的命令输出 JSON 计划,包含 mode、变更文件、选择理由与测试清单。发票文件变化时,mode 是 affected,清单为 invoice.test.mjs 加 smoke.test.mjs。它不会运行测试,也不会改 CI 配置。传入文件名只是在申报改动范围,脚本不会自动读取 Git diff。

这里故意使用手写映射,既不是 Anthropic 的历史结果服务,也不是自动采集的覆盖率依赖图。AI 可以帮忙解释路径、提出可能缺失的关系,但解释听起来合理,并不能证明映射完整。

输出建议集合,保留 JSON 作为依据
node select.mjs src/invoice.mjs

# 选择的测试文件:
# tests/invoice.test.mjs
# tests/smoke.test.mjs

信息不确定,就回退全量

试试下面四条命令,每条都会返回 mode: full 和完整的三个测试。未知文件、共享文件和配置变更也回退全量。空变更列表、无效映射或不兼容的布局版本,都不能悄悄变成“零测试”。

两个不确定性参数需要特别理解:这个练习不能自行发现文件删除、重命名、不完整 diff,或结构正常但已经过时的映射,调用者必须主动标记。映射中的 layoutRevision 只是人工兼容标记,不是提交检查。真实系统要先有持续维护的依赖与版本依据,才有理由相信较小的集合。

验证四种保守回退
node select.mjs new-file.mjs
node select.mjs --uncertain-history src/invoice.mjs
node select.mjs --map-stale src/invoice.mjs
node select.mjs --map missing.json src/invoice.mjs

用全量对照,抓住“选得很自信,但选错了”

先运行下面正常的 shadow 命令。它会在独立 Node 进程中实际运行选择集和完整三个测试,包内默认示例两组都通过。终端的 output 字段指向新建的 .results/run-* 目录,里面有 summary.json 与每个测试的日志。

再运行故意出错的那一条:它只申报发票变化,却让通知模块返回错误消息。选中的发票和冒烟测试仍通过,全量运行则在通知测试失败。summary.json 的 omittedFailures 会列出被漏掉的测试,命令退出码为 1。这正是练习期望看到的结果,不应为了变绿而删掉通知断言。

这个参数模拟的是错误的影响范围信息,不会发现真实依赖,也不会修改源文件。它把一个本来会被“选择集全绿”掩盖的失败显露出来。正常示例通过,只能说明这个小型本地例子通过。

先正常对照,再刻意暴露一次漏选
node shadow.mjs src/invoice.mjs

# 预期退出码为 1;查看 omittedFailures
node shadow.mjs --simulate-missed-dependency src/invoice.mjs

给 Onevium 一个能核对的调查任务

在打开练习目录的会话里,用输入框 @ 文件列表引用 ci-runs.json 和 dependency-map.json,再发送下面的请求。把结果目录占位符替换为刚才命令实际输出的路径。最终需要的是引用文件和运行结果的简短解释,你可以拿终端记录逐项核对。

用于真实团队时,先导出耗时数据,只增加建议集合的影子报告,继续让原有全量 CI 决定是否通过。在相同代码版本与环境下比较,记录漏掉的失败、回退频率、选择器自身耗时与排队时间,再讨论改变策略。仅仅少了几个红灯,不能证明缺陷变少。

可以直接改路径后使用的提示词
读取本练习的 ci-runs.json、dependency-map.json,
以及 .results/<实际运行目录>/summary.json。
说明每次运行主要耗在哪一段。
解释这次模拟失败为什么被选择集漏掉,
引用具体测试路径和结果字段。
把实际观察与建议分开写。
不要改文件、删测试、改 CI、提交或推送。
证据不足就列出缺口,不要猜测。

下一步只做一个小对照

本文实际验证的是离线 Node 练习:选择规则、回退行为、耗时算术、真实本地测试运行,以及全量对照发现一次故意设置的漏选。它不能证明真实模型质量、生产安全或某个提效百分比。

这一组教程建议按顺序实践:先分清复杂任务由谁负责,再在这里排查测试等待,接着用团队 Skill 保存可重复方法,最后衡量整段工作流。顺序只是帮助落地;如果你已经明确卡在 CI,也可以从本文开始。下一步挑一个有代表性的真实变更,保留全量测试,只做一次影子报告,并指定一个人核对差异。