传统自动化测试并没有过时。真正失效的,是“给定输入、断言唯一输出”这一种测试思路。Agent 会调用工具、修改环境并在多轮决策中改变路径;要判断它能否上线,必须同时测试确定性组件、关键轨迹、最终状态和多次运行的可靠性。

一个普通函数很好测试:传入参数,执行代码,断言返回值。
一个 AI Agent 却不只返回一段文字。它可能先搜索代码,再读取文件,修改实现,运行测试,发现失败后继续修复,最后告诉你“任务已经完成”。
问题在于,这句话可能是真的,也可能只是模型对当前状态的误判。
如果测试只检查最终回答里有没有“已修复”,一个没有修改任何文件的 Agent 也能通过;如果把每一次工具调用的顺序全部写死,Agent 换一种同样有效的解法又会被误判失败。
所以,Agent 测试最难的不是写更多断言,而是重新定义“什么叫通过”。
本文以 AI 编程 Agent 为例,建立一套五层测试体系:确定性组件测试、工具与策略测试、轨迹评测、最终状态评测,以及基于多次试验的发布门禁。这套方法同样适用于客服、研究、数据分析和浏览器操作 Agent。
一、不是传统测试失效了,而是被测对象变了
传统自动化测试通常隐含一个前提:在相同代码、输入和环境下,系统会沿着相对稳定的路径产生可预测结果。
Agent 的被测对象却是一个组合系统:
模型 + 提示词 + Agent 调度器
+ 工具定义 + 外部环境 + 运行时状态
这里任何一项变化,都可能改变下一步决策。
模型输出本身可能在不同运行中产生差异;文件、网页、数据库和搜索结果会变化;工具超时可能触发重试;上下文裁剪可能让 Agent 忘记先前信息;一次错误参数还可能改变后续环境,让错误沿多轮链路继续放大。
Anthropic 在 Agent 评测实践中把一次任务运行称为 trial,把完整消息、工具调用和中间结果称为 transcript、trace 或 trajectory,并特别区分了 Agent 最后“声称完成”与环境中任务是否真的完成。
这个区分非常重要:回答是证词,环境状态才是证据。

传统单元测试依然适合验证工具函数、权限规则、Schema、幂等逻辑和状态机。它没有失效,只是无法独自回答三个新问题:
- Agent 选择了正确的工具吗?
- 它是否以允许的方式完成任务?
- 这种成功能否在多次运行中稳定复现?
二、第一层:先把确定性部分测到足够可靠
不少团队一开始就用大模型评判另一个大模型,反而忽略了最便宜、最快、最容易定位问题的传统测试。
Agent 系统中仍有大量确定性组件:
- 工具参数能否通过 JSON Schema 校验;
- 文件路径是否被限制在工作区;
- 数据库写入是否使用幂等键;
- 当前身份是否有权调用某个工具;
- 重试是否只针对允许重试的错误;
- 超过步数、Token 或时间预算后是否停止;
- 工具返回异常时,状态机是否进入正确分支。
这些内容应该继续使用单元测试、集成测试、静态分析和契约测试。只要能用代码给出确定答案,就不应优先交给 LLM Judge。
以一个修改代码的工具为例,最重要的测试不是模型会不会调用它,而是工具本身是否守住边界:
def test_write_file_rejects_outside_workspace():
result = write_file("../../secrets.txt", "x")
assert result.error == "PATH_NOT_ALLOWED"
如果确定性执行层允许越权路径,后面无论增加多少提示词和评测,都只是在测试一个没有安全边界的系统。
三、第二层:Mock 工具,测试 Agent 会不会做出正确决定
确定工具本身可靠后,再测试 Agent 的决策逻辑。
这时可以把真实工具替换为可控的 Mock:搜索工具固定返回三条结果,文件读取工具返回指定内容,测试命令第一次失败、第二次通过。这样既能复现异常路径,也能避免网络、数据库和第三方服务给评测引入额外噪声。
这一层关注的不是回答文风,而是行为边界:
- 信息不足时是否先询问,而不是猜测参数;
- 无需工具时是否避免多余调用;
- 工具失败后是否按错误类型处理;
- 高风险操作前是否请求确认;
- 参数是否来自用户输入或可信上下文;
- 同一个失败是否陷入无限循环。
测试集一定要同时包含正例和反例。
如果所有样本都要求 Agent 搜索,最终可能训练出“任何问题都先搜索”的行为;如果只测试工具调用成功,就无法发现它在不该调用时仍然调用。Anthropic 的评测实践也强调,应同时覆盖某种行为应该发生和不应该发生的场景,避免单向优化。
Mock 也有边界。它适合快速、稳定地验证决策,但无法发现真实工具的鉴权、限流、协议和数据差异。因此发布前还需要少量契约测试和隔离环境中的真实端到端测试,不能把 Mock 的成功当作生产成功。

四、第三层:不要锁死完整路径,只断言关键轨迹
Agent 常常可以通过多条路径完成同一任务。
修复一个分页 Bug,它可以先阅读 Controller,也可以先运行失败测试;可以一次定位根因,也可以经历一次错误假设后纠正。只要最终修复正确,这些路径都可能合理。
因此,严格匹配完整工具序列通常很脆弱。提示词或模型稍有变化,测试就会大量失败,却未必代表产品质量下降。
更实用的做法,是把轨迹断言分成四类:
- 必须发生:最终回答前必须运行目标测试;
- 禁止发生:不得修改工作区外文件,不得调用生产写接口;
- 顺序约束:执行部署前必须先通过测试和审批;
- 预算约束:工具调用、Token、时间和重试次数不能无限增长。

LangChain 的 Agent Evals 文档把轨迹匹配分为 strict、unordered、subset 和 superset 等方式。这个分类并不意味着必须使用某个框架,但提供了一个很好的工程视角:
- 安全或合规要求需要固定顺序时,才使用严格匹配;
- 多个查询顺序无关时,只检查调用集合;
- 只允许白名单工具时,检查实际调用是否为允许集合的子集;
- 必须完成若干动作但允许额外探索时,检查是否包含最低要求。
核心原则是:对关键约束严格,对合法路径宽容。
如果测试规定 Agent 必须先读 service.py 再读 test_service.py,它可能只是在复刻测试作者的思路;如果测试规定“修改后必须运行相关测试,且不得改动认证模块”,它才是在验证业务真正关心的行为。
五、第四层:最终状态比最后一句话更可信
轨迹合理,不代表任务已经完成。
Agent 可能调用了正确工具,却给出错误参数;可能运行了测试,却忽略失败结果;也可能修复一个用例,同时破坏原有功能。
因此,端到端评测应该直接检查环境结果。
对编程 Agent,可以检查:
- 目标失败测试是否转为通过;
- 原有测试是否仍然通过;
- 代码能否编译并通过静态检查;
- 变更是否限制在允许目录;
- 是否引入无关依赖、大面积重写或隐藏配置;
- Git Diff 是否真正对应任务要求。
SWE-bench 的基本思路就是把真实代码仓库和问题描述交给模型,让其修改代码,再通过测试验证最终补丁。它的价值不在某个排行榜数字,而在于把“会不会写一段看起来合理的代码”推进到“能否在真实仓库环境中解决问题”。
对其他 Agent,最终状态同样可以被确定性检查:
- 客服 Agent:退款记录是否真实存在,金额和订单是否匹配;
- 数据 Agent:查询结果是否来自允许的数据集,计算是否可复核;
- 浏览器 Agent:目标表单是否提交成功,是否误改其他字段;
- 研究 Agent:关键结论是否有来源支持,引用是否确实包含相关内容。
AgentBench 将 Agent 放入多种交互环境中评估,也说明单轮问答不足以覆盖多轮决策和环境交互能力。
六、第五层:一次通过,不能证明它稳定
传统测试习惯把结果写成绿色或红色。Agent 更适合被看成一个带成功概率的系统。
同一个任务运行一次通过、下一次失败,并不罕见。只跑一次,就无法判断修改带来的差异是真实回归,还是随机波动。
因此,每个重要任务都应运行多次 trial,并根据产品场景选择指标:
- pass@1:第一次尝试成功的比例,适合用户只给一次机会的场景;
- pass@k:多次尝试中至少一次成功,适合系统允许生成多个候选再验证的场景;
- pass^k:连续多次都成功,适合强调一致性的客服、审批或自动执行场景。
不要只汇总一个“综合得分”。任务成功、安全违规、成本和延迟具有不同含义,应该分别设门槛。
例如,一个编程 Agent 的发布条件可以写成:
correctness:
no_significant_regression: true
safety:
forbidden_write_count: 0
efficiency:
tool_calls_p95_below_limit: true
quality:
critical_cases_all_pass: true
这里的具体阈值必须来自业务风险、历史基线和样本规模,不能照抄别人。更重要的是,安全关键项不应被其他高分“平均掉”:一次生产越权写入,不应该因为回答风格很好而获得及格分。

七、LLM Judge 可以用,但不能成为唯一裁判
开放式任务很难全部用代码判断。
例如,代码修改是否过度设计、解释是否遗漏关键风险、研究报告是否真正回答问题,这些维度适合使用带评分标准的 LLM Judge。
但模型裁判同样具有不确定性,还可能偏好某种表达方式。因此可以建立三层 grader:
- 代码型评分器:测试、Schema、状态、权限、成本和明确规则;
- 模型型评分器:按单一维度的明确 Rubric 评估开放式质量;
- 人工评审:校准模型评分器,检查高风险和争议样本。
Anthropic 的实践建议是:能确定性判断时优先使用代码,开放问题再使用模型评分,并用人类专家校准。也不要让一个 Judge 一次判断所有维度;把“事实正确”“是否遵循指令”“是否过度修改”拆开,结果更容易解释。
还要防止评测被“投机通过”。如果 Agent 能读取测试答案、历史轨迹或评分脚本,它可能找到满足断言却没有真正完成任务的捷径。评测环境必须隔离答案和隐藏检查,参考解也应实际运行一次,以证明任务可解、评分器没有写错。
八、一条失败记录,至少要能回答三个问题
当一个评测失败时,团队首先要区分:
- Agent 失败:选错工具、参数错误、推理中断或忽略结果;
- 环境失败:网络波动、共享状态、资源不足或测试数据污染;
- 评分失败:任务描述含糊、断言过严、参考答案错误或 Judge 漂移。
如果只保存最终回答,这三个问题几乎无法区分。
一次 trial 至少应记录:
- 任务、样本和 trial 标识;
- 模型、提示词、Agent 代码与工具 Schema 版本;
- 脱敏后的消息、工具参数、工具结果和错误;
- 环境初始快照与最终状态;
- 每个评分器的版本、分数和理由;
- Token、工具次数、首字延迟、总耗时和重试次数。
轨迹记录的目的不是无限保存所有内容。提示词、代码、数据库结果和工具参数都可能包含敏感数据,应根据数据分级执行脱敏、访问控制和保留周期。
九、把生产失败变成可重复的回归样本
一套有价值的 Agent 测试集,不是从网上抄来的几十个通用问题,而是产品成功标准的可执行版本。
建议把样本分成五类:
- 能力样本:产品承诺必须完成的核心任务;
- 回归样本:历史缺陷、用户投诉和线上失败;
- 边界样本:缺字段、超长输入、工具超时和部分成功;
- 反向样本:不应调用工具、不应执行、不应回答的场景;
- 对抗样本:越权请求、提示词注入、恶意文件和评分绕过。
每个样本不要只保存一个问题,还要保存环境夹具、成功状态、禁止状态、预算、评分器和重复运行次数。
task: fix-pagination-bug
fixture: repo-snapshot-v3
success: target-and-regression-tests-pass
forbidden: edit-auth-module
budget: 20-tool-calls
trials: 5
这里的数字只是结构示例,不是通用推荐值。高风险、低成功率或波动较大的任务,需要更多试验;快速 PR 检查则可以运行小型确定性集和少量烟雾评测。
十、让评测真正进入发布流程
如果评测只能在某位工程师电脑上手动运行,它很快会失去约束力。
可以把 Agent 测试分为三个速度层级:
每次提交:快而确定
- 工具单元测试和契约测试;
- 权限、Schema、幂等和状态机测试;
- 少量关键轨迹与安全烟雾样本;
- 不依赖真实外部服务的 Mock 环境。
每晚运行:覆盖波动
- 完整任务集的多次 trial;
- 真实或高保真隔离工具环境;
- 成功率、成本、延迟和工具调用分布;
- 与当前生产基线进行统计比较。
发布前:验证真实风险
- 高风险任务和历史严重失败全部通过;
- 新旧模型、Prompt、工具或 Skill 使用同一套数据对比;
- 人工抽查轨迹和模型评分器分歧样本;
- 灰度发布后继续监控真实任务完成率。
发布门禁应该保存完整实验配置,而不只是一个分数。否则模型版本、提示词、工具或评测数据一变,团队就无法复现“当时为什么允许上线”。
十一、最常见的六个测试误区
1. 只测最终文本
Agent 可以用正确语气描述一个从未发生的动作。应检查真实环境状态。
2. 把工具顺序全部写死
过于严格的轨迹会惩罚合法解法。只固定安全关键顺序和必要动作。
3. 只运行一次
单次结果无法反映可靠性。关键任务需要多次 trial,并报告分布而非孤立分数。
4. 全部交给 LLM Judge
模型评分适合开放式质量,不应替代测试、权限和状态断言。
5. 所有工具都使用 Mock
Mock 会隐藏真实协议、鉴权、限流和数据差异。发布前必须保留隔离环境的契约和端到端测试。
6. 评测集长期不更新
样本会饱和,生产分布也会变化。持续加入真实失败,并淘汰含糊、重复或已失去区分度的任务。
写在最后
AI Agent 上线前,传统自动化测试并没有突然失效。
真正失效的,是把 Agent 当成普通函数,只断言一次输入对应的一段输出。
可靠的 Agent 测试体系应该做到五件事:
- 用传统测试守住工具、权限和状态机这些确定性底座;
- 用 Mock 场景验证工具选择、参数和异常决策;
- 用轨迹断言约束必要动作、禁止动作和资源预算;
- 用环境状态证明任务真的完成;
- 用多次试验和分维度门禁判断它是否稳定到可以上线。
最终要测的,不是 Agent 某一次能不能给出漂亮答案,而是它在允许的成本和权限内,能否一次又一次把真实任务做对。
测试回答,只能证明它会说;测试轨迹和结果,才能证明它会做。
参考资料
- Anthropic:Demystifying evals for AI agents
https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents - LangChain Docs:Agent Evals
https://docs.langchain.com/oss/python/langchain/test/evals - AgentBench:Evaluating LLMs as Agents
https://arxiv.org/abs/2308.03688 - ICLR 2024:SWE-bench
https://proceedings.iclr.cc/paper_files/paper/2024/hash/edac78c3e300629acfe6cbe9ca88fb84-Abstract-Conference.html
夜雨聆风