☰
自用Agent全功能测试实录:工具调用、记忆模块与任务编排的边界验证
2026/10/20 23:43:10 网站建设 项目流程

1. 为什么我要给自己的 Agent 做一次全面功能测试

做 Agent 开发的人都有一个通病:功能越加越多,心里越来越没底。我自己的这个自用 Agent 从最初只有一个对话入口,到现在挂了工具调用、记忆管理、多轮任务编排、文件读写、定时触发这几大块,代码量翻了三倍,但真正系统性地跑一遍全功能测试,一直拖着没做。直到上周连续踩了两次坑——一次是记忆模块把上一轮的工具返回结果当成了用户输入,另一次是任务编排在并发场景下把两个不相关的任务串到了一起——我才下定决心,花整整两天时间,把这个 Agent 从里到外测了一遍。

这篇内容就是这次测试的完整记录。我会把测试思路、每个模块的具体测法、用到的工具和脚本、踩到的坑以及最后的修复方案全部摊开讲。适合两类人看:一类是自己也在写 Agent、想知道别人怎么做功能验证的开发者;另一类是刚接触 Agent 概念、想了解一个完整 Agent 到底包含哪些功能模块、每个模块容易在哪里出问题的学习者。我不会讲太多理论,重点放在“怎么测”和“测出来什么”上,所有步骤都可以直接抄。

先说一下我这个 Agent 的基本情况,方便你对照自己的项目。它是一个跑在本地环境里的自用助手,核心能力包括:自然语言对话、工具调用(主要是文件操作和命令执行)、短期记忆与长期记忆、多步骤任务拆解与执行、定时任务触发。没有接入任何外部平台,所有逻辑都在本地闭环。技术栈是 Python 为主,记忆层用了一个轻量向量库,任务编排是自己写的一个简易调度器。整个项目大概两千多行代码,不算大,但功能点很密集。

测试的核心目标有三个:第一,确认每个功能模块在正常输入下能正确工作;第二,确认模块之间的边界在异常输入下不会互相污染;第三,确认长时间运行后不会出现内存泄漏或状态错乱。这三个目标决定了我的测试不能只做“happy path”,必须刻意制造脏数据、并发和长链路场景。

2. 测试前的准备工作与整体设计思路

2.1 先画一张功能地图,别急着写测试用例

我见过很多人一上来就开始写测试脚本,结果测到一半发现漏了整个模块。我的做法是先把 Agent 的所有功能点列成一张地图。具体操作是:打开代码目录,从入口文件开始,沿着调用链把每个对外暴露的能力都记下来。这个过程大概花了四十分钟,最后得到的功能清单是这样的:

  • 对话入口:单轮问答、多轮上下文保持、超长输入截断
  • 工具调用:文件读取、文件写入、目录列举、命令执行、工具参数校验
  • 记忆模块:短期记忆写入与读取、长期记忆检索、记忆去重、记忆过期清理
  • 任务编排:单任务拆解、多任务串行、多任务并行、任务失败重试
  • 定时触发:定时器注册、定时器触发、定时器取消

这张地图的好处是,它让我清楚地看到哪些功能是“叶子节点”(不依赖其他模块),哪些是“复合节点”(依赖多个模块)。叶子节点可以单独测,复合节点必须做集成测试。比如“工具调用”里的文件读取是叶子节点,而“任务编排”里的多任务并行就是复合节点,它依赖工具调用和记忆模块。

提示:功能地图不需要多漂亮,用纸笔或者纯文本列出来就行。关键是每个功能点后面标注它的依赖关系,这决定了你测试的执行顺序。

2.2 测试环境隔离,这一步绝对不能省

自用 Agent 最容易犯的错误就是拿生产环境直接测。我一开始也这么干过,结果测试产生的脏数据把长期记忆污染了,后面好几天的对话都怪怪的。这次我专门做了环境隔离,具体做法是:

把 Agent 的配置抽成一个独立的配置文件,测试时通过环境变量指向另一套配置。这套测试配置里,记忆库指向一个临时目录,工具调用的工作目录指向一个沙箱文件夹,定时器的触发间隔调短以便快速验证。这样测试产生的所有副作用都限制在沙箱里,测完直接删目录就行。

另外我准备了一个测试数据生成脚本,用来造各种边界输入。这个脚本不复杂,核心就是几个函数:生成超长字符串、生成包含特殊字符的字符串、生成嵌套的 JSON、生成并发调用序列。这些在后面各个模块的测试里反复用到。

2.3 测试用例的分层策略

我把测试用例分成三层。第一层是单元级,针对叶子节点,输入输出明确,断言简单。第二层是集成级,针对复合节点,重点验证模块间的数据传递是否正确。第三层是压力级,针对长时间运行和并发场景,重点看状态是否一致。

分层的意义在于定位问题。如果单元级全过、集成级挂了,那问题一定出在模块间的接口上,不用去翻每个模块的内部实现。这个思路在后面的排查里帮我省了大量时间。

3. 核心功能模块的逐项测试实录

3.1 对话入口:超长输入和上下文污染是重灾区

对话入口看起来最简单,但实际测下来问题不少。我设计的测试用例包括:正常单轮问答、连续十轮上下文保持、单次输入超过模型上下文窗口、输入包含大量特殊字符、输入为空。

正常单轮和连续多轮都没问题,Agent 能正确保持上下文。问题出在超长输入上。我的处理逻辑是超过阈值就截断,但测试发现截断后 Agent 的回答质量明显下降,因为它把截断后的半句话当成了完整语义。更严重的是,截断产生的残缺内容被写进了短期记忆,导致后续几轮对话都受影响。

修复方案是在截断前先做一次语义完整性检查,如果截断点落在句子中间,就往前找到最近的句号或换行符再截。同时截断事件本身要记一条日志,但不写入记忆。这个改动大概二十行代码,但效果立竿见影。

特殊字符测试也发现了一个小问题:输入里包含连续多个换行符时,Agent 的分段逻辑会把它们当成多个空段落处理,导致上下文长度计算偏大。修复方法是预处理阶段把连续换行合并成一个。

注意:对话入口的测试一定要覆盖“输入为空”的情况。我实测发现空输入会触发一个未捕获的异常,虽然不影响主流程,但日志里会刷一堆错误堆栈,干扰排查。

3.2 工具调用:参数校验和沙箱边界必须死磕

工具调用是 Agent 最容易出安全问题的模块,因为涉及文件读写和命令执行。我的测试重点是参数校验和沙箱边界。

参数校验方面,我针对每个工具都造了非法参数。比如文件读取工具,测试了路径为空、路径不存在、路径指向目录、路径包含上级跳转符号这几种情况。实测发现路径包含上级跳转符号时,Agent 没有做拦截,直接读到了沙箱外的文件。这是个严重问题,修复方案是在路径解析后做一次规范化,然后检查规范化后的路径是否仍在沙箱根目录下,不在就拒绝。

命令执行工具的测试更谨慎。我造了一组测试命令,包括正常命令、返回非零退出码的命令、输出超长的命令、执行时间超长的命令。实测发现执行时间超长的命令会把整个 Agent 阻塞住,因为我没有设超时。修复方案是给命令执行加一个可配置的超时参数,默认三十秒,超时后强制终止并返回错误。

沙箱边界测试还发现一个隐蔽问题:文件写入工具在目标目录不存在时会自动创建目录,但创建逻辑没有做权限检查,导致在某些系统路径下会失败并抛出未处理的异常。修复方案是创建目录前先检查父目录是否可写。

测试项输入预期实测修复
路径跳转../outside.txt拒绝读取成功增加规范化校验
命令超时sleep 60超时终止阻塞增加超时参数
目录创建/root/test拒绝异常增加可写检查

3.3 记忆模块:去重和过期清理最容易出 bug

记忆模块是我这次测试花时间最多的部分,因为它直接决定了 Agent 的“智商”表现。测试用例包括:写入新记忆、读取相关记忆、重复写入相同内容、写入高度相似内容、过期记忆清理、记忆检索的召回率。

重复写入测试发现,相同的记忆内容会被多次写入,导致检索时返回一堆重复结果。修复方案是在写入前做一次相似度检查,超过阈值就跳过。这里有个细节:相似度阈值不能设太高,否则语义相同但表述不同的记忆会被漏掉;也不能设太低,否则会把相关但不相同的记忆误判为重复。我实测下来零点八五左右比较合适,但这个值跟具体的向量模型有关,需要根据实际情况调。

过期清理测试发现,清理逻辑只在 Agent 启动时执行一次,运行过程中不会触发。这意味着如果 Agent 长时间不重启,过期记忆会一直堆积。修复方案是加一个定时清理任务,每小时执行一次。

记忆检索的召回率测试比较麻烦,我造了一百条测试记忆,然后针对其中二十条造查询,看能否正确召回。实测召回率大概在百分之七十五左右,漏掉的主要是表述差异较大的情况。这个暂时没有完美解法,我的处理是在检索时多返回几条候选,让上层逻辑再做一次筛选。

提示:记忆模块的测试数据一定要用真实场景的文本,不要用“测试记忆一”“测试记忆二”这种。因为向量检索对语义敏感,假数据测不出真实问题。

3.4 任务编排:并发场景下的状态隔离是难点

任务编排是复合节点,依赖工具调用和记忆模块。我设计的测试用例包括:单任务正常执行、多任务串行执行、多任务并行执行、任务中途失败、任务重试。

单任务和串行都没问题。问题出在并行执行上。我让 Agent 同时执行两个任务,一个读文件一个写文件,结果发现两个任务共享了同一个上下文对象,写文件的任务把读文件任务的中间状态覆盖了。这是个典型的状态隔离问题。修复方案是给每个任务分配独立的上下文副本,任务之间通过明确的返回值传递数据,不共享可变对象。

任务失败重试也发现一个问题:重试时没有重置任务状态,导致重试的任务带着上次失败的残留数据继续执行。修复方案是重试前先做一次状态清理。

任务中途失败的测试还暴露了一个日志问题:失败任务的错误信息没有带上任务 ID,导致排查时不知道是哪个任务挂了。修复方案是在所有任务相关日志里统一加上任务 ID 前缀。

3.5 定时触发:时间精度和重复触发要重点验证

定时触发模块相对独立,测试用例包括:注册定时器、等待触发、取消定时器、重复注册同一时间点、触发时 Agent 正忙。

注册和触发的基本功能没问题。问题出在重复注册上:同一时间点注册两个定时器,两个都会触发,但我的预期是只触发一个。修复方案是在注册时做去重,相同时间点和相同回调的定时器只保留一个。

触发时 Agent 正忙的情况也值得说。实测发现如果 Agent 正在执行一个长任务,定时器触发会被延迟到任务结束后,这本身没问题,但延迟期间如果又到了下一个触发点,就会连续触发两次。修复方案是给定时器加一个“触发中”标记,触发期间忽略新的触发请求。

时间精度方面,我实测下来定时器的误差在几十毫秒级别,对于自用场景完全够用。如果你的场景对精度要求更高,可能需要换用更底层的定时机制。

4. 测试过程中踩到的坑与排查技巧

4.1 日志是排查的第一抓手,但要先治理日志

这次测试我最大的体会是:没有好日志,排查就是盲人摸象。我一开始的日志很乱,各个模块各写各的,格式不统一,关键信息缺失。后来我花了一个小时做日志治理,统一了格式,每条日志都带上时间戳、模块名、任务 ID(如果有)、日志级别。治理之后排查效率至少提升一倍。

具体做法是封装一个日志函数,所有模块都通过它输出。日志格式用 JSON,方便后续用脚本分析。关键路径上增加 DEBUG 级别日志,记录输入输出和中间状态。生产运行时把级别调到 INFO,测试时调到 DEBUG。

4.2 用最小复现用例定位问题,不要一上来就改代码

遇到问题时,我的习惯是先写一个最小复现用例,把问题稳定复现出来,再动手改。这次测试里有个记忆检索的 bug,一开始以为是向量库的问题,写了个最小用例后发现是检索前的文本预处理把关键词过滤掉了。如果直接去翻向量库的代码,可能半天都找不到原因。

最小复现用例的写法很简单:把触发问题的输入固定下来,去掉所有无关的依赖,只保留最核心的调用链。能稳定复现之后,再逐步加回依赖,看问题在哪个环节出现。

4.3 常见问题速查表

现象可能原因排查方向修复思路
回答质量突然下降记忆被污染检查最近写入的记忆清理脏记忆,加写入校验
工具调用报路径错误沙箱边界失效检查路径规范化逻辑增加规范化后校验
任务结果串台上下文共享检查任务上下文创建每个任务独立上下文
定时器重复触发去重缺失检查注册逻辑增加去重和触发标记
长时间运行变慢内存泄漏检查对象引用及时释放不再使用的对象

4.4 几个容易被忽略的测试细节

第一个细节是时区。我的定时器测试一开始没考虑时区,结果在跨时区场景下触发时间偏了几个小时。修复方案是统一用 UTC 时间存储,展示时再转本地时区。

第二个细节是编码。文件读写测试里,我用了包含中文和 emoji 的文本,发现写入时没指定编码会导致乱码。修复方案是所有文件操作显式指定 UTF-8 编码。

第三个细节是并发数。并行任务测试时,我一开始只测了两个任务并行,后来加到十个,发现调度器的队列处理有问题,任务会丢失。修复方案是给队列加锁,并增加队列满时的拒绝策略。

5. 测试之后的收尾与持续验证

5.1 把测试用例固化成脚本,别只跑一次

这次测试的用例我没有用完就扔,而是整理成了一个测试脚本集。每个模块一个脚本,用 pytest 组织,可以一键跑全部。脚本里保留了所有边界用例和回归用例。这样以后每次改代码,跑一遍脚本就能知道有没有引入新问题。

脚本的组织方式是按模块分文件,每个文件里按功能点分测试类。测试数据用 fixture 管理,测试环境用临时目录,跑完自动清理。整个脚本集跑一遍大概三分钟,完全可以接受。

5.2 加一个健康检查接口,随时看 Agent 状态

测试完之后我给 Agent 加了一个健康检查接口,返回各个模块的状态:记忆库大小、最近一次工具调用时间、当前运行中的任务数、定时器数量。这个接口不对外暴露,只在本地调用。有了它,我随时能知道 Agent 是不是正常,不用等到出问题才发现。

健康检查的实现很简单,每个模块暴露一个 status 方法返回字典,健康检查接口把它们汇总一下返回 JSON。耗时不到五十毫秒,对性能没影响。

5.3 后续还可以扩展的测试方向

这次测试主要覆盖了功能正确性和基本的并发场景,还有几个方向可以继续深入。一个是长稳测试,让 Agent 连续跑二十四小时,看内存和状态的变化。一个是模糊测试,用随机生成的输入去撞边界。还有一个是性能测试,测各个模块的响应时间,找出瓶颈。

我个人的经验是,自用 Agent 的测试不用追求大而全,但核心链路的边界一定要覆盖到。尤其是工具调用和记忆模块,这两个地方出问题的影响最大。测试脚本写一次,后面每次改代码都能用,这个投入是值得的。

最后分享一个小技巧:测试的时候把 Agent 的日志级别调到 DEBUG,同时开一个终端实时看日志输出。很多问题在日志里其实有迹可循,只是平时级别太高看不到。我这次至少有三个 bug 是通过实时看日志发现的,比事后翻日志快得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询