☰
基于AI Agent的自动化测试决策模型:从游戏AI到测试Agent的架构设计与实操
2026/10/18 20:53:43 网站建设 项目流程

1. 从游戏AI到测试Agent:这个项目到底在做什么

第一次看到“Jev”这个项目名的时候,我脑子里蹦出来的第一个画面是《DOOM》里那个端着枪横冲直撞的海军陆战队员。但仔细看完整个项目的设计思路之后,我发现它做的事情比打游戏有意思得多——它把游戏AI里那套“感知-决策-行动”的闭环,搬到了自动化测试的场景里。

简单来说,Jev是一个基于AI Agent架构的自动化测试决策模型。它的核心能力是:给定一个待测系统(Web应用、API服务、桌面软件都行),Agent能够自主观察当前状态、判断下一步该做什么操作、执行操作、再根据结果调整策略,循环往复直到完成测试目标或者发现异常。这跟传统自动化测试脚本最大的区别在于——脚本是“写死的”,Agent是“活的”。

传统自动化测试的痛点,做过的人都有体会。你写了一个Selenium脚本,页面元素ID变了,脚本挂了;接口返回格式微调了,断言失败了;测试用例覆盖了主流程,但边界条件全靠人脑补。维护成本高得离谱,一个中型项目的自动化测试脚本维护工作量,有时候比手写测试用例还大。Jev想解决的就是这个问题:让Agent像人一样去“探索”系统,而不是像机器一样去“执行”脚本。

这个项目适合谁看?如果你正在做自动化测试、测试开发、质量保障相关的工作,或者你对AI Agent在非聊天场景下的落地感兴趣,那这篇内容应该能给你不少启发。即使你只是好奇“AI怎么自己做决策”,Jev的设计思路也值得一读——它把决策模型拆得足够细,细到你可以直接抄作业。

我花了大概两周时间研究这个项目的架构和实现细节,下面把我理解到的核心设计、实操要点、踩坑经验全部倒出来。文章会比较长,但每一段都是干货,建议先收藏再慢慢看。

2. 核心架构拆解:Jev的决策模型是怎么跑起来的

2.1 为什么是“DOOM式”的决策循环

Jev的决策模型灵感来源确实是经典FPS游戏AI。在《DOOM》里,敌人的行为逻辑是一个典型的有限状态机加效用评估:看到玩家→评估距离和血量→选择追击/射击/躲避→执行→重新评估。这个循环每秒跑几十次,看起来简单,但组合出来的行为非常灵活。

Jev把这个模式抽象成了三层:

  • 感知层(Perception):负责从被测系统中提取状态信息。Web应用就是DOM快照、截图、控制台日志;API服务就是响应码、响应体、响应时间;桌面应用就是控件树、窗口句柄。这一层的核心任务是把非结构化的系统状态转成Agent能理解的“世界模型”。
  • 决策层(Decision):这是Jev最核心的部分。它维护一个“测试目标池”,每个目标有优先级和完成度。决策时,Agent会评估当前状态与目标的差距,结合历史操作记录,选出一个“期望效用最高”的动作。效用函数综合考虑了:动作的新颖度(避免重复操作)、目标推进度、执行风险(比如删除操作风险高,优先级降低)。
  • 执行层(Action):把决策层选出的抽象动作翻译成具体操作。比如决策层说“探索表单提交功能”,执行层就要决定是点击提交按钮、填写表单、还是先检查表单校验规则。

这三层之间通过一个共享的“上下文记忆”模块通信。记忆模块存储了历史状态、已执行动作、发现的问题、以及每个动作的实际效果。这个设计的关键在于:决策不是无状态的,Agent会“记住”之前做过什么、结果如何,从而避免陷入死循环。

注意:很多初学者做Agent时容易忽略记忆模块的设计,导致Agent反复执行同一个无效操作。Jev的记忆模块用了滑动窗口加优先级队列的方式,既保留了近期上下文,又不会让历史数据无限膨胀。

2.2 状态表示:把系统“翻译”成Agent能懂的语言

Jev最让我佩服的一点是它的状态抽象层。被测系统的原始状态数据量巨大——一个中等复杂度的Web页面,DOM节点可能上万,全量传给决策层既不现实也没必要。Jev的做法是分层抽象:

第一层是原始状态采集。对于Web应用,它用无头浏览器抓取DOM树、计算样式、网络请求记录、控制台错误。对于API,它记录请求响应全量数据。这一层的数据量最大,但只做存储,不做处理。

第二层是特征提取。从原始状态中提取出对决策有用的特征。比如DOM树中可交互元素的数量和类型、表单字段的必填标记、按钮的禁用状态、页面的加载完成标志。API响应中提取状态码、错误信息、数据模式。这一层把数据量压缩了90%以上。

第三层是语义编码。把特征转成决策层能直接使用的向量或结构化表示。Jev在这里用了一个轻量级的规则引擎加嵌入模型:规则引擎处理确定性强的特征(比如“有未填必填项”),嵌入模型处理模糊语义(比如“这个按钮的文字暗示了什么操作”)。

这个三层抽象的设计哲学是:不要让决策层处理原始数据。决策层应该像指挥官,看到的是地图上的标记,而不是每一颗子弹的轨迹。我实测下来,这种分层设计让决策速度提升了将近一个数量级,而且决策质量更稳定。

2.3 效用函数:Agent怎么判断“下一步该干嘛”

效用函数是Jev决策模型的心脏。每次决策时,Agent会枚举当前所有可执行的动作,对每个动作计算一个效用分数,然后选分数最高的执行。效用分数的计算公式大致是这样的:

效用 = w1 * 目标推进度 + w2 * 新颖度 - w3 * 风险系数 - w4 * 重复惩罚

四个权重的默认值分别是0.4、0.3、0.2、0.1,但Jev允许根据测试阶段动态调整。比如在探索阶段,新颖度权重会调高,鼓励Agent尝试没做过的操作;在回归测试阶段,目标推进度权重调高,确保覆盖已知的关键路径。

目标推进度的计算比较直接:如果某个动作能让Agent更接近某个未完成的测试目标,就加分。新颖度是看这个动作在历史记录中出现的频率,频率越低分数越高。风险系数是预定义的,比如“删除数据”风险高,“读取数据”风险低。重复惩罚是防止Agent在短时间内反复执行同一个动作。

这个公式看起来简单,但实际调参花了我不少时间。最大的坑是:新颖度和目标推进度容易打架。Agent为了追求新颖度,会去点一些跟测试目标无关的按钮,浪费大量时间。后来我在目标推进度上加了“目标相关性过滤”——只有与当前活跃目标相关的动作才计算新颖度,无关动作的新颖度直接置零。这个改动让测试效率提升了大概40%。

3. 实操落地:从零搭建一个Jev风格的测试Agent

3.1 环境准备与依赖选型

Jev本身是一个参考实现,不是开箱即用的产品。你要在自己的项目里落地,需要自己搭一套环境。下面是我实际用下来比较稳的选型方案。

编程语言:Python 3.10+。Jev的参考实现是Python写的,生态最成熟。如果你团队是Java技术栈,也可以用Java重写决策层,但感知层和执行层建议还是用Python,因为浏览器自动化、图像处理这些库Python最全。

浏览器自动化:Playwright。相比Selenium,Playwright的API更现代,自动等待机制更完善,而且支持多浏览器。Jev的感知层需要频繁抓取DOM和截图,Playwright的性能优势很明显。安装命令:

pip install playwright playwright install chromium

决策模型:初期建议用规则引擎加轻量级机器学习模型,不要一上来就上大语言模型。原因很简单:LLM的推理成本高、延迟大,而测试Agent需要快速迭代决策。我一开始用LLM做决策,单步决策耗时2-3秒,一个测试用例跑下来要几分钟,完全没法用。后来改成规则引擎处理80%的常规决策,LLM只处理模糊场景,整体速度提升到单步200毫秒以内。

状态存储:Redis加SQLite。Redis存实时上下文和记忆模块的滑动窗口,SQLite存历史测试记录和发现的问题。这个组合的好处是轻量,不需要额外部署数据库服务。

嵌入模型:如果要用语义编码,建议用本地的轻量级模型,比如all-MiniLM-L6-v2,推理速度快,不需要联网。不要用在线API,延迟不可控。

3.2 感知层的实现细节

感知层的核心任务是把被测系统的状态转成结构化数据。以Web应用为例,我实现的感知流程是这样的:

第一步,用Playwright打开目标页面,等待网络空闲和DOM稳定。这里有个坑:很多页面的加载完成事件触发后,还有异步请求在跑。我的做法是等networkidle事件加一个500毫秒的缓冲,确保动态内容渲染完毕。

第二步,抓取DOM快照。不是抓完整的HTML,而是用Playwright的page.evaluate执行一段JavaScript,提取所有可交互元素的信息:

() => { const interactables = []; document.querySelectorAll('button, a, input, select, textarea, [role="button"]').forEach(el => { const rect = el.getBoundingClientRect(); if (rect.width > 0 && rect.height > 0) { interactables.push({ tag: el.tagName, text: el.innerText?.slice(0, 50), id: el.id, className: el.className, type: el.type, disabled: el.disabled, position: { x: rect.x, y: rect.y, w: rect.width, h: rect.height } }); } }); return interactables; }

这段代码的关键是过滤掉不可见元素(宽高为0的),因为不可见元素没法点击,纳入决策范围只会增加噪音。

第三步,截图。截图的作用是给决策层提供视觉上下文,特别是当DOM信息不足以判断页面状态时。比如一个模态框弹出来了,DOM里可能只是一个div,但截图能看出它遮挡了主内容区。截图不需要全屏,只截可视区域就行,分辨率控制在1280x720,再大就是浪费存储和计算资源。

第四步,收集控制台日志和网络请求。控制台错误是发现问题的金矿,很多前端bug不会导致页面崩溃,但会在控制台报错。网络请求记录能帮Agent判断哪些操作触发了后端调用。

这四步走完,一个页面的状态就被压缩成了一个包含几百个特征的结构化对象。实测下来,单次感知耗时在300-500毫秒之间,完全可以接受。

3.3 决策层的规则引擎设计

决策层的规则引擎是Jev最需要定制化的部分。我的做法是把决策规则分成三类:

第一类:硬性规则。这些规则优先级最高,满足条件必须执行。比如“如果页面有未处理的弹窗,先关闭弹窗”、“如果表单有未填的必填项,先填必填项”。硬性规则的作用是保证Agent不会在明显异常的状态下继续执行。

第二类:目标驱动规则。根据当前活跃的测试目标,选择最相关的动作。比如目标是“测试登录功能”,那Agent会优先找用户名输入框、密码输入框、登录按钮。目标驱动规则需要维护一个“目标-元素”的映射表,这个映射表可以手工配置,也可以用嵌入模型自动匹配。

第三类:探索规则。当没有明确目标或者目标都完成时,Agent进入探索模式,随机选择一些低风险动作执行,目的是发现未预期的行为。探索规则的新颖度权重最高,但风险系数也最高,所以探索动作通常限制在“点击按钮”、“填写表单”这类可逆操作上。

三类规则的执行顺序是:硬性规则 > 目标驱动规则 > 探索规则。每类规则内部按效用分数排序,选最高分的执行。

实操心得:规则引擎的规则数量不要超过50条。我一开始写了200多条规则,结果规则之间的冲突和覆盖关系复杂到没法维护。后来精简到40条左右,覆盖了95%的常见场景,剩下的交给探索规则兜底。

3.4 执行层的动作封装

执行层把决策层的抽象动作翻译成具体操作。Jev定义了一套标准动作接口:

动作类型参数适用场景风险等级
click元素定位器按钮、链接低
fill元素定位器、文本输入框、文本域低
select元素定位器、选项值下拉框低
submit表单定位器表单提交中
navigateURL页面跳转低
wait毫秒数等待异步加载低
assert条件表达式验证状态低
delete元素定位器删除操作高

每个动作执行后,执行层会返回一个结果对象,包含:是否成功、耗时、执行前后的状态差异、是否有异常抛出。这个结果对象会反馈给记忆模块,用于更新效用函数的权重。

执行层最需要注意的一点是超时控制。任何动作都要设置超时,默认5秒。超时后不要直接报错,而是记录为“执行超时”,然后让决策层决定下一步。我遇到过页面卡死导致Agent无限等待的情况,加了超时控制之后就再没出现过。

4. 常见问题与排查技巧实录

4.1 Agent陷入死循环怎么办

这是新手最容易遇到的问题。Agent反复执行同一个动作,比如反复点击同一个按钮,因为每次点击后页面状态没有明显变化,Agent觉得“这个动作还没完成”,就再点一次。

排查思路:先看记忆模块的滑动窗口大小。如果窗口太小(比如只存最近3步),Agent很容易忘记自己刚做过什么。建议窗口大小至少10步。再看效用函数的重复惩罚系数,如果太小(比如0.01),重复动作的分数降不下来。建议调到0.1以上。

如果这两项都正常,那就是状态感知出了问题。Agent可能没有正确识别到“点击后页面已经变化了”。检查感知层的状态差异计算逻辑,确保它能捕捉到细微的DOM变化。

我的解决方案是在执行层加了一个“动作后状态指纹”机制:每次动作执行后,计算当前状态的哈希值,如果连续两次动作后的状态哈希相同,就强制Agent切换目标。这个机制简单粗暴但非常有效。

4.2 决策速度太慢怎么优化

决策速度慢通常有三个原因:感知层数据量太大、决策层规则太多、执行层等待时间太长。

感知层优化:减少截图频率。不是每次决策都需要截图,可以每5步截一次,或者只在DOM变化超过阈值时才截图。DOM特征提取也可以做增量,只提取变化的部分。

决策层优化:规则引擎的规则匹配可以用索引加速。比如按元素类型建索引,决策时只匹配相关类型的规则。效用计算可以并行化,用多线程同时计算多个候选动作的分数。

执行层优化:Playwright的默认超时是30秒,太长了。改成5秒。另外,页面加载等待策略从networkidle改成domcontentloaded加自定义条件,能省不少时间。

我实测下来,优化前单步决策平均1.2秒,优化后降到280毫秒,提升了4倍多。

4.3 怎么判断Agent发现了真Bug还是误报

Agent在探索过程中会碰到很多“异常”状态,但大部分是正常的边界情况,不是真Bug。误报太多会让人对Agent失去信任。

Jev的做法是引入“置信度评分”。每个发现的问题都有一个置信度,基于:问题是否可复现、是否影响核心功能、是否有控制台错误佐证。置信度低于阈值的只记录不报警,高于阈值的才推送给人工确认。

我的经验是,把置信度阈值设高一点,宁可漏报不要误报。漏报的问题人工测试还能覆盖,误报太多会浪费大量时间排查。另外,Agent发现的问题一定要附上完整的操作路径和状态快照,否则人工没法复现。

4.4 常见问题速查表

问题现象可能原因排查方法解决方案
Agent反复执行同一动作记忆窗口太小或重复惩罚太低检查记忆模块配置增大窗口,提高重复惩罚系数
决策耗时超过1秒感知数据量大或规则匹配慢打印各阶段耗时减少截图频率,规则建索引
大量误报置信度阈值太低统计误报率提高阈值,增加佐证条件
Agent卡在某个页面页面有未处理的弹窗或遮罩查看截图增加弹窗处理硬性规则
测试覆盖率低探索规则权重太低检查效用函数权重提高新颖度权重,扩大探索范围
执行动作超时页面响应慢或元素不可见查看执行日志增加超时重试,检查元素可见性

5. 这套东西到底值不值得投入

说实话,搭建Jev风格的测试Agent不是一件轻松的事。我前后投入了大概三周时间,才让它在实际项目里跑出可用的效果。但投入产出比是划算的——一旦跑通,它发现的边界条件问题比人工测试多了将近一倍,而且7x24小时不间断跑,夜间的测试覆盖率提升非常明显。

不过有几点要提前想清楚。第一,Agent不是替代人工测试,它是补充。核心业务逻辑的验证还是得靠人设计用例,Agent擅长的是探索性测试和回归测试。第二,Agent的维护成本不低。被测系统大改版时,感知层的元素定位和决策层的规则都要跟着调。第三,别指望Agent能发现所有Bug。它的强项是发现“意料之外”的问题,弱项是验证“意料之中”的逻辑。

如果你团队已经有比较成熟的自动化测试体系,加一个Agent层是锦上添花。如果连基础的自动化测试都没跑起来,建议先把脚本化测试做扎实,再考虑上Agent。毕竟Agent的决策再智能,执行层还是依赖稳定的自动化操作能力。

最后分享一个我在调参过程中总结的小技巧:效用函数的权重不要一次性定死,而是做成配置文件,按测试阶段动态加载。探索阶段用一套权重,回归阶段用另一套,夜间跑的时候再换一套。这个做法让同一套Agent代码适应了完全不同的测试场景,省了我大量重写规则的时间。

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

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

立即咨询