智能体测试策略:单元测试、集成测试与模拟LLM

从"修了三个月bug,改一个坏三个"到"改完Prompt敢直接上线",我踩过的坑和总结出来的路

先讲个让我至今后背发凉的事。

去年做了一个自动审批报销单的Agent,逻辑不复杂:读邮件里的发票图片,OCR提取金额,跟公司预算系统比对,低于500块自动批,超过的转人工。测试阶段跑了五十多个case,全过。信心满满上线。

第二周,财务总监在群里发了一张截图,问"这个报销是怎么回事"。

我点开一看,Agent把一个3520元的差旅住宿费,判断成了520元,自动批准了。原因是一个实习生写Prompt的时候,在金额提取的描述里写了一句"如果有小数点,只取整数部分"。结果35.20变成了35,再乘以100变成了3520?不,它把小数点后面的"20"识别成了20元,然后做了一个迷之运算,输出了520。

更让我崩溃的是,我花了三天时间修好了这个问题,然后跑回归测试,发现另一个case又开始报错了------Agent开始把"500.01"识别成"500",导致一个刚超过自动审批阈值的报销单被错误地自动批了。

这就是智能体测试和传统软件测试最大的区别。在传统代码里,你修好一个if语句,所有依赖这个if的路径都会一起被修好。但Agent的"代码"是Prompt,是LLM的推理路径。你修好了A场景,B场景可能因为Prompt的变化而变差。你永远无法像断言函数返回值那样,断言一个LLM的"思考过程"。

那之后,我花了半年时间,系统性地研究了智能体的测试策略。这篇文章,我就把这段经历浓缩成一套可落地的测试框架:从单元测试怎么Mock LLM,到集成测试怎么验证工具调用链,再到端到端测试怎么模拟真实用户,以及2026年有哪些工具能让这事儿不那么痛苦。

一、为什么智能体测试比传统软件测试难十倍?

在深入具体策略之前,先搞明白为什么这事儿这么难。我把它总结为四个根本原因。

1. 非确定性输出:同样的输入,不同的输出

传统程序是确定性的。你给add(2, 3),它永远返回5。Agent呢?你问"今天天气怎么样",模型可能回答"今天晴天,22度",也可能回答"天气晴朗,体感舒适,大约22度"。两个答案都对,但你没法写一个断言说"必须包含'晴天'"或者"必须包含'22度'"。更麻烦的是,遇到模糊需求,模型的输出可能天差地别。你没法用简单的等值断言来验证。

2. 多步骤依赖:第一步错,后面步步错

ReAct模式下,Agent的每一步决策都依赖前一步。Monday Service团队在技术复盘里提到,一个小错误在早期被传播开来,可能会导致后面完全不同且错误的输出------一个Prompt或工具调用结果的轻微偏差,可能在整个任务链中被显著放大。你修复了第三步的bug,但第一步的Prompt改动可能导致第二步走了一条完全不同的分支,第三步根本没走到你修复的那条路。

3. 状态爆炸:执行路径的组合太多了

一个20步的任务,每一步可能有3-5种不同的分支(取决于工具返回结果、用户反馈、模型自己的"思考")。组合起来,可能的执行路径数量是天文数字。你不可能穷举所有路径来测试。更别提Agent还有记忆------上次对话中用户说过的话,会影响这次的决策。传统测试里没有这种"跨会话污染"的问题。

4. 环境依赖:Agent活在真实世界里

Agent要调用真实API,真实API会超时、会改版、会限流。你本地跑测试的时候一切正常,一上线,第三方物流接口改了个字段名,Agent开始把"已签收"识别成"运输中"。这不是Agent的问题,但它确实导致了错误。这些外部依赖的不确定性,让测试变得极其困难。

面对这四个挑战,很多团队的选择是------不测试了,直接上线,出了问题再修。结果就是每个周末都在加班修线上bug。我觉得这条路走不通。经过半年的摸索,我们总结出了一个三层测试体系,让这个问题至少变得可控。

二、智能体测试的三层体系

传统的软件测试有单元测试、集成测试、端到端测试。智能体测试也借鉴了这个分层思想,但每一层的内涵和工具完全不同。

  • 单元测试:验证Agent的单步决策逻辑,比如"给定这个用户输入,Agent会不会调用正确的工具、提取正确的参数"。这一层需要用Mock LLM来隔离外部依赖,确保测试是确定性的。
  • 集成测试:验证Agent的工具链集成和状态管理,比如"调用订单查询工具后,状态里有没有正确记录订单号""多轮对话中记忆有没有正确更新"。这一层需要真实的工具调用(或者在可控的沙箱环境中运行)。
  • 端到端测试:模拟真实用户的完整交互流程,覆盖正常流程和异常流程,比如"用户发起退款→Agent要求提供订单号→用户提供→Agent执行退款→通知用户"。

下面我们一层一层来拆。

三、单元测试:用Mock驯服LLM的"任性"

单元测试的目标是验证Agent的决策逻辑------给定一个输入,Agent会不会做出正确的决策、调用正确的工具、提取正确的参数。

在传统软件里,单元测试很简单:你mock掉外部依赖(比如数据库、API),只测试函数本身的逻辑。在Agent的世界里,最大的外部依赖就是LLM本身。如果我们不Mock LLM,每次跑单元测试都要等几秒钟(LLM推理时间)、花几分钱(token费用),而且结果还不稳定------今天跑过了,明天模型升级了可能就挂了。

那怎么Mock LLM?

2026年的工具生态给出了不错的答案。MockLLM是一个可扩展的Mock服务器,用于模拟大语言模型API,支持插件式架构,可以轻松添加新的提供商模拟器而不修改核心代码。它能够为你提供确定性、可配置的响应,非常适合测试和评估场景。pytest-mockllm是一个零配置的pytest插件,可以mock OpenAI、Anthropic、Gemini、LangChain等多种LLM API,让你测试AI应用的时候不用真的调用模型,既省token又快。

有了这些工具,我们可以这样写一个单元测试:

python 复制代码
def test_weather_agent_calls_correct_tool():
    # 1. 设置Mock LLM,让它"假扮"成真实的模型
    mock_llm = MockLLM()
    mock_llm.add_response("""
    思考: 用户想查北京的天气,我需要调用get_weather工具。
    行动: {"tool": "get_weather", "args": {"city": "北京"}}
    """)
    
    # 2. 用Mock LLM初始化Agent
    agent = WeatherAgent(llm=mock_llm)
    
    # 3. 执行测试
    result = agent.process("北京今天天气怎么样?")
    
    # 4. 验证Agent调用了正确的工具
    assert agent.last_tool_call.name == "get_weather"
    assert agent.last_tool_call.args["city"] == "北京"

这个测试可以在几毫秒内跑完,不需要真实LLM调用,不需要网络,不需要花钱。你可以把这个测试放在CI里,每次提交代码自动跑。

但Mock LLM有一个关键问题:你Mock的响应应该是什么?

你需要在Mock的响应里模拟Agent的"思考-行动"输出。这意味着你必须在写测试的时候,就知道"对于这个输入,Agent应该输出什么"。这看起来像是"作弊",但实际上是单元测试的本质------你在验证Agent的编排逻辑,而不是在测试LLM本身。

为了生成高质量的Mock响应,我们团队采用了一个策略:先用真实模型(比如GPT-5)跑一遍测试用例,把它的思考轨迹记录下来,作为后续单元测试的Mock基准。这样你既保证了Mock的真实性,又不用每次都调用昂贵的大模型。

用deepeval做LLM单元测试

除了Mock LLM,还有一个思路是用专门的LLM评估框架来做"语义级别的单元测试"。DeepEval是一个开源的LLM评估框架,类似于Pytest但专门为LLM应用设计。它支持通过G-Eval、任务完成度、答案相关性、幻觉等多种指标进行评估,这些评估基于LLM-as-a-judge和其他在你的机器上本地运行的NLP模型。

DeepEval有几个专门针对Agent的评估指标,可以直接用来做单元测试:Tool Correctness检查是否调用了正确的工具和参数;Goal Accuracy衡量Agent达成目标的准确度;Step Efficiency评估Agent是否走了不必要的步骤;Plan Adherence检查Agent是否遵循了预期的计划。这些指标的价值在于,你不需要手动写规则来判定"调用工具是否正确",直接让评估框架来做,比自己写正则表达式靠谱得多。

四、集成测试:验证Agent与世界的"握手"

单元测试保证了Agent的"大脑"在Mock环境下的正确性。但Agent能干活,是因为它能和外部世界互动------调用工具、读写数据库、发送邮件。集成测试的任务就是验证这些"握手"是否正常。

1. 工具调用链验证

假设你的Agent在执行"查订单"任务时,需要依次调用get_order_info(获取订单详情)和get_logistics_info(获取物流信息)。集成测试需要验证:工具是否按正确的顺序被调用,参数传递是否正确,中间状态是否有正确记录。

百度开发者中心的一篇文章给出了一个很好的示例结构,针对日历调度智能体验证工具调用正确性:

python 复制代码
class CalendarAgentTest(TestCase):
    def test_memory_update(self):
        # 初始化测试环境
        env = TestEnvironment(mock_fs=True)
        agent = CalendarAgent(env)
        
        # 执行测试指令
        response = agent.process("永远不要在9点前安排会议")
        
        # 验证执行轨迹
        self.assertEqual(env.mock_fs.last_path, "/memories/preferences.json")
        self.assertIn("no_morning_meetings", env.mock_fs.last_content)
        
        # 验证最终状态
        self.assertTrue(response.contains("记忆已更新"))

这个示例里,TestEnvironment提供了一个可控的测试环境(包括Mock的文件系统)。测试可以断言Agent是否在正确的路径写入了正确的配置,而不仅仅是检查最终的回答。

2. 多轮对话状态验证

集成测试的另一大重点是验证多轮对话中的状态管理。一个日历调度Agent的核心需求可能包括:记忆用户设定的会议时间偏好(比如"禁止早9点前会议")、动态协调参会人时区冲突、自动生成会议纪要并归档。传统测试只能验证最终会议时间是否符合约束,但集成测试需要确认用户偏好是否持久化存储到指定文件路径、时区转换工具是否被正确调用两次(发起者+参与者)、会议纪要是否包含所有决议项。

3. LangGraph的检查点机制:集成测试的秘密武器

LangGraph内置的检查点(Checkpoint)机制,是集成测试的杀手锏。检查点会在图的每个超级步骤自动保存状态快照,包括对话历史、工具调用记录、所有中间变量。在集成测试中,你可以在Agent执行完成后,通过get_state_history()拉出完整的执行轨迹,然后逐段验证------比如第3步用户说了什么、第5步Agent调用了什么工具、第8步状态里记录了什么偏好。LangGraph的时间旅行能力允许你在任意检查点位置注入新状态后继续执行,或者在某个历史检查点分叉出一条新的时间线并行验证。这对于集成测试来说价值巨大------你可以让两个Agent从同一个检查点出发,一个走A路径,一个走B路径,对比结果。

4. CrewAI的AgentEvaluator框架

如果你用的是CrewAI框架,它的AgentEvaluator框架专门为多智能体集成测试设计。它通过监听crewai_event_bus上的Agent事件来运作,当Agent完成任务时,触发配置的评估指标。内置的评估指标包括GoalAlignmentEvaluator(目标对齐)、SemanticQualityEvaluator(语义质量)等。在集成测试中,你可以用AgentEvaluator框架来验证整个Crew的任务执行结果是否符合预期。

五、端到端测试:让Agent在"真实世界"里跑一遍

单元测试验证了决策逻辑,集成测试验证了工具交互,但这两层都是在受控环境下跑的。Agent最终要在真实世界里面对真实用户------模糊的需求、意外的输入、情绪化的表达、外部服务的不稳定。端到端测试就是模拟这些真实场景,验证Agent在混沌环境中的表现。

1. 真实用户场景模拟

端到端测试最核心的内容是模拟真实用户的多轮交互。三层测试框架建议构建包含以下要素的测试框架:对话状态管理器维护跨轮次上下文,用户模拟器生成符合行为模式的输入序列,响应验证器检查输出连贯性和正确性。一个典型的多轮测试场景包括:用户设置偏好→智能体记录状态;用户发起请求→智能体结合历史状态响应;用户修改偏好→智能体更新状态并反馈。

Zendesk在2025年底分享了一个非常实用的方法:从真实生产对话中提取测试用例。他们从真实客服对话中提取数据,将对话拆分为带有预期API结果的独立测试用例。这种方法的好处是测试数据来自真实世界,不是人工臆造的,覆盖了真实用户可能提出的各种边缘问题。

2. 异常流程验证

除了"用户正常使用"的场景,端到端测试还必须覆盖各种异常。工具调用失败怎么办、网络超时怎么办、用户输入恶意指令怎么办、LLM产生幻觉怎么办等等。

异常场景需要在测试中有意识地注入。你可以通过Mock外部服务返回错误码来模拟工具失败,或者通过在沙箱中设置延迟来模拟网络波动。百度开发者中心的文章提到,测试环境应该实现三级管理------基础环境标准化操作系统和依赖库,服务镜像容器化部署测试依赖服务,数据隔离确保每个测试用例使用独立数据空间。通过环境标准化,某实践案例将测试结果波动率从28%降至3%以内。

3. 混沌测试与对抗性测试

2026年还有一个值得关注的测试方向是"混沌测试"。LangSmith平台提供了三层次测试方案,其中第三层就是混沌测试------模拟异常输入、网络延迟等边界条件。更前沿的方向是用AI来测试AI。例如TAI3框架能够系统性地发现LLM Agent中的意图完整性违规,生成基于工具包文档的真实测试任务,并应用定向变异来暴露Agent中的错误,同时保持用户意图不变。另一篇论文介绍了Neo框架,它耦合了问题生成Agent和评估Agent,通过共享上下文中心来模块化地组合领域提示、场景控制和动态反馈,实现可配置的多轮自动化评估。

六、2026年的智能体测试工具链

理论讲完了,下面推荐几个我们团队在用、也觉得确实好用的工具。

LangSmith------大语言模型应用的全生命周期管理平台,提供开发工作台、测试验证中心、部署编排系统、监控告警体系四大模块,通过统一数据总线实现各模块数据互通,形成"开发-测试-部署-监控-优化"的完整闭环。Monday Service团队基于LangSmith构建了一个代码优先的测试框架,将AI Agent的评估时间从162秒缩短到了18秒,提升了8.7倍。

DeepEval是专门为LLM应用设计的单元测试框架,支持Agentic Metrics(任务完成度、工具正确性、目标准确度等)和RAG Metrics(答案相关性、忠实度等)。它的价值在于用标准化指标替代手工编写验证规则。

CrewAI本身也是一套测试框架,除了前面提到的AgentEvaluator,还可以用promptfoo对CrewAI Agent进行结构化评估,定义测试提示、检查输出、运行自动化对比,甚至进行红队测试来捕捉意外的失败。CrewAI的AgentEvaluator采用事件驱动架构拦截Agent执行并应用特定评估指标。

LangGraph的检查点系统除了用于状态管理和故障恢复,本身也是强大的调试和测试工具。时间旅行能力包括get_state_history(像Git log一样浏览全部历史检查点)、Fork(从历史快照分叉出新的执行分支)、update_state(在任意检查点注入新状态后继续执行)。当集成测试失败时,你可以直接从生产环境拉出失败的trace,转化为单元测试用例,完全复现当时的执行环境,然后在本地调试,修好了再上线。

七、CI/CD集成与测试左移

说了这么多测试方法,如果没有嵌入到开发流程中,效果会大打折扣。

把Agent测试嵌入CI/CD流水线的实践方案已经非常成熟。离线评估作为"单元测试"在代码合并前运行,在线评估监控生产流量。Monday Service的做法是将评估逻辑放在TypeScript文件中,走PR评审流程,通过CI/CD部署------工程师合并PR时,系统自动将Prompt定义推送到LangSmith注册中心,同时自行编写测试来验证评估器本身的准确性。

"测试左移"------在开发阶段尽早引入测试的理念至关重要。智能体评估体系应引入测试左移策略。当你修改Prompt时,立刻跑一遍回归测试,确保改动没有破坏已有功能。

数据集管理与版本控制是测试左移的基础。LangSmith支持带版本化的示例数据集、自定义评估器(确定性的和LLM-as-a-judge)、Agent行为的轨迹评估,以及跨运行的实验对比。每次Prompt修改都应该对应一个数据集版本,你可以在LangSmith里对比v1和v2在不同数据集上的表现,数据驱动决策。

八、从零搭建:一个分阶段的测试路线图

最后,根据团队的实际经验,总结一个从零搭建智能体测试体系的分阶段路线图。

第一阶段:手动验证 + 简单断言(MVP阶段)

目标:验证核心流程能跑通。做法是用5-10个核心场景手动测试,确认Agent能完成最重要的任务。不用写自动化测试,但要记日志------把Agent的思考过程、工具调用、最终输出都记下来。这个阶段大概持续1-2周。

第二阶段:Mock LLM + 单元测试(稳定期)

当核心逻辑确定后,引入pytest-mockllm或类似工具,为核心工具调用决策编写Mock测试。用deepeval补充语义验证,确保核心功能不会被后续改动破坏。这个阶段大概需要2-3周。

第三阶段:集成测试 + 状态验证(成长期)

Agent开始处理更复杂的多步任务后,启用LangGraph检查点,编写集成测试验证工具调用链。为多轮对话场景编写状态验证测试,确保Agent不会"失忆",状态在不同轮次间正确传递。这个阶段大概需要3-4周。

第四阶段:端到端测试 + CI/CD集成(成熟期)

从真实生产数据构建测试集,接入LangSmith做全链路评估。关键场景设置自动化回归测试,评估结果与CI/CD流水线集成。这个阶段大概需要4-6周。

第五阶段:混沌测试 + 对抗性测试(企业级)

模拟外部服务故障、网络延迟、异常输入等边界条件,验证Agent在极端情况下的表现。对高风险Agent引入红队测试,定期评估安全性。

写在最后

回到文章开头的报销Agent。那次事故之后,我们彻底重构了测试流程。现在,每次修改Prompt,都会触发一个包含200+单元测试、50+集成测试和20+端到端测试的流水线。虽然跑一遍要十几分钟,但再也没有出现过"改一个坏三个"的情况。

智能体测试不是在限制你迭代的速度,而是在保护你迭代的方向。没有测试的Agent迭代,就像在雷区里跑步,你永远不知道下一步会不会踩到雷。建立测试体系确实需要投入------需要时间、需要工具、需要改变开发习惯。但长期来看,这是省时间,而不是浪费时间。

最后送你一句话:在AI Agent开发中,测试不是在代码写完后再做的事,测试和开发是同一件事。

相关推荐
小羊Yveesss6 小时前
AI智能单元测试:覆盖率泡沫与可信测试的产业破局
人工智能·单元测试
测试员周周10 小时前
【AI测试路线图2】功能测试转 AI 测试:4~5 个月,一条最稳的路
开发语言·人工智能·python·功能测试·测试工具·单元测试·pytest
川石课堂软件测试11 小时前
接口测试常见面试题及答案
python·网络协议·mysql·华为·单元测试·prometheus·harmonyos
MC皮蛋侠客12 小时前
Catch2 单元测试指南
单元测试·catch2
诸葛李12 小时前
集成构建xxxxx
java·junit·单元测试
yeshan1 天前
【Draft】基于 cluacov 的 Lua 代码分支覆盖率统计:从行级近似到指令级精确
单元测试·lua
姚青&1 天前
测试体系与测试方案设计
单元测试
QH139292318802 天前
R&S®SMBV100B 矢量信号发生器 5G/Wi-Fi/GNSS 主力源
网络·科技·嵌入式硬件·集成测试·信息与通信