移动端自动化测试在接入大模型之后,最大的变化不是“执行更快了”,而是“维护逻辑变了”。过去我们维护一套 UI 用例,核心资产是控件定位表达式和页面对象模型,每次版本迭代光修 locator 就要花掉三分之一的时间。走到这个系列的第七篇,我想认真聊聊 Mobile-Agent-v3 和自研 GUI-Owl 模型这条路线——前者是人气持续走高的开源智能体框架,后者是我们团队在生产环境里坚持自研的视觉感知路线。两条路线解决的问题其实是同一个:怎么让模型真正“看懂”移动端屏幕,并稳定地输出可执行的动作。这篇文章会把两套方案的内部机制、训练数据构造、部署链路和实测数据全部摊开来讲,适合已经在做移动端自动化、正准备向 LLM 驱动方案迁移的测试开发同学参考。
1. 为什么移动端 UI 测试到了必须换路线的拐点
1.1 传统自动化框架的维护成本是线性增长的
很多团队在移动端自动化上走过相似的路径:从纯坐标脚本,到控件树定位,再到引入 OCR 做兜底。但这三种方式都有同一个根源问题——它们都是“规则驱动”的,规则越多,维护成本越不可控。
拿控件树定位来说,App 版本更新后 LinearLayout 变成了 ConstraintLayout,或者某个控件加了新的 id 前缀,脚本立刻挂掉。OCR 也有自己的毛病,服务端返回的动态字段、图片上的活动文案、深色模式下的前景色变化,都会让识别结果突然不可用。我在某金融理财 App 的回归测试里见过最典型的一个例子:首页资产卡片上的数字从普通字体切成 DIN 字体后,全部 OCR 断言批量失败,排查花了两天,最后发现只是字体变更导致字符分割偏移了三个像素。
坐标脚本更不用提,不同分辨率的适配几乎靠“堆叠 if 语句”,一套 300 条的冒烟用例,每季度要整体修复一轮。这不是某个方案不够好,而是移动端 UI 本身具备高度的视觉驱动特性,规则驱动的自动化永远在“被 UI 变更牵着走”的被动位置。
1.2 LLM 进来之后,范式悄悄完成了切换
大模型驱动的自动化测试,核心变化是把“脚本描述状态”换成了“模型理解屏幕”。测试用例不再需要逐行写清楚某个按钮在哪个父节点下、偏移量是多少、等多少秒出现,而是直接给模型一个任务指令,比如“进入资产页面,确认昨日收益数值已刷新”,模型自己完成屏幕感知、目标定位、动作规划、结果验证这条链路。
这样一来,UI 变动带来的维护冲击被大幅吸收。控件树变了、元素层级重构了,只要视觉呈现没有本质变化,模型依然能依靠截图内容完成任务。我们在实验组的数据很直接:UI 回归用例的脚本维护时间从每周 6 人时降到每周 1.5 人时,但用例数量并没有减少,这是规则框架做不到的。
1.3 移动端场景的特殊约束决定了技术选型方向
移动端自动化比 Web 端更麻烦的地方在于约束条件非常多:屏幕尺寸碎片化、页面层级深、有横竖屏切换、有 Native 与 WebView 混排、有各类系统权限弹窗和广告卡片。更重要的是,移动端的用户路径是高度“非线性的”,一个任务往往要跨越三个以上的页面,甚至在多个 App 之间来回跳转。
Mobile-Agent-v3 这类方案之所以被关注,就是因为它从设计上就针对这些约束做了处理:以截图视觉输入为主、保留 XML 层级作为辅助信号,动作空间收敛为少量原子操作,并支持跨应用路径规划。它不是简单把 Web 端的思路搬过来,而是真正往“移动智能体”的方向走了。这也是我们后来敢于选择自研 GUI-Owl 模型的信心来源——先看清楚这个拐点,再决定自己站在哪里。
2. Mobile-Agent-v3 的动作收敛:从“看到屏幕”到“知道下一步点哪里”
2.1 输入输出链路与感知层设计
Mobile-Agent-v3 的处理链路可以拆成四个环节:任务解析、屏幕感知、动作决策、执行反馈。任务解析发生在真实设备操作之前,模型先把用户给出的自然语言指令拆成可验证的子目标。比如“帮我把收货地址改成公司地址”这个任务,会先拆出“打开个人中心”“进入地址管理”“修改地址”“保存并验证”这样一个粗粒度的步骤序列——这只是规划,不是最终动作。
屏幕感知环节是 v3 比较有代表性的部分。它不像 Appium 那样依赖控件树解析,而是把当前屏幕截图 + 组件层级信息一起丢给视觉语言模型,让模型根据屏幕内容直接判断“现在处于什么页面”“哪些元素可以交互”“下一步该做什么”。这里有一个容易被忽略的细节:视觉感知是带空间锚定的。模型不是只输出“我看到一个返回按钮”这样的描述,还需要把按钮的坐标区域、控件类型、可操作状态一并输出,后续的动作决策才有落点。
这个设计的妙处在于:它把“理解”和“定位”合在了一起。传统自动化里,理解和定位是两个步骤——OCR 负责理解、坐标表负责定位,任何一边出错都会导致失败。v3 把两端放进同一个模型,降低了对中间特征的依赖,也减少了定位漂移带来的连锁故障。
2.2 动作空间为什么这么设计
Mobile-Agent-v3 将动作输出收敛为 Tap、Input、Swipe、Back、Open App 等少数几类。为什么要收敛?因为动作空间太大,模型决策的复杂度会指数级上升。想象一下,如果模型需要自己生成一段可编程的点击路径,而不是输出一个简单的“点击坐标”,那么每次决策都相当于一次程序生成,错误率必然高。
实际执行时,模型输出的动作会带上必要的参数。Tap 动作输出坐标或目标元素 ID,Input 动作输出目标字段和文本内容,Swipe 动作输出起点、终点和持续时间。通过护栏层把动作参数限制在合法范围内(比如点击不能落在控件边界之外、输入长度有上限),从而避免模型偶尔出现的幻觉参数导致设备长期处于异常状态。
我们还发现一个容易被忽略的点:no-op 动作(不做操作的观察动作)在 v3 中的价值非常大。模型在验证页面刷新完成、确认状态变更时,需要“看一眼就行”的能力。如果强行让每个决策都产生物理操作,反而会在等待网络请求的间隙产生大量误触。v3 对 no-op 的支持,其实是在教会模型“什么时候不该动手”。
2.3 跨应用协作与任务记忆
移动端任务往往不是单 App 内的线性操作。典型场景是:从被测 App 跳到另一个 App,执行某操作后,再跳回来继续验证。Mobile-Agent-v3 在 v3 版本里引入了 App 图标感知机制来应对跨应用路径——模型需要识别屏幕上出现的不同 App 图标,并理解“现在进入的是另一个应用,需要切换到对应的操作上下文”。
我做了一个假设:移动智能体最容易被低估的是“任务记忆”。屏幕信息是瞬时的,如果没有上下文记忆,模型在第二步就会忘记第一步的目标。“进入个人中心—点地址管理—点新增地址”这个三步任务,当完成第二跳时,模型必须记得它正处于“新增地址”的子流程中,且原始用户目标是“修改收货地址”。
v3 的实现套路是维护一个内部状态队列,把子目标、已执行动作、待验证结果都放进短期记忆,每一步动作都基于“历史记忆 + 当前屏幕”联合决策。这样设计带来的直接收益是,模型不会在跨 App 跳转回来之后误认为自己需要重新开始。我们在某音视频应用的实测中,加入任务记忆后,长链路任务的步骤准确率从 63% 提升到了 82%,这个提升幅度比任何感知模块的升级都明显。
3. 自研 GUI-Owl 模型路线:我们决定不坐等框架升级的理由与做法
3.1 再好的开源方案,也未必兜得住你的业务界面
Mobile-Agent-v3 本身已经很能打,但当我们把它放进生产环境时,还是遇到了几个绕不过去的真实问题。
第一个是业务控件语义偏差。金融 App 里的 K 线图、理财收益卡、风险评估问卷里的滑块组件,在通用模型眼里就是“一堆图形”,模型往往识别不出“这是可以拖拽的风险偏好滑块”。另一个问题是深色模式与动态品牌视觉。很多业务已经全面切到深色模式,背景色从白色变成深灰色,通用模型的视觉特征会产生偏移,按钮识别率和区域定位准确率明显下降。第三个问题是专业术语与断言逻辑,模型不了解“昨日年化收益”“待收本金”“冻结金额”等业务字段之间的勾稽关系,也就无法在测试用例里完成有效的状态验证。
这三个问题有一个共同点:它们不是通用感知能力不够,而是领域专用知识不足。这促使我们开始思考自研路线——不推翻 Mobile-Agent-v3 的智能体框架,但要替换和增强它的视觉感知底座,让模型真正理解自家业务的 UI 语义。
3.2 GUI-Owl 的模型结构:双流输入与对齐训练
自研 GUI-Owl 模型的结构设计,一开始的目标就不是“再做一个通用 VLM”,而是做一个面向 UI 理解的专用视觉编码器 + 定位头。它的核心结构包括双流输入、UI 语义编解码和动作映射三部分。
双流输入是 GUI-Owl 最有特点的设计。路径一接收原始屏幕截图,通过视觉编码器提取像素级特征;路径二接收控件树的轻量特征(例如控件的类型、文本内容、布局坐标、可见性),编码成结构信息向量。两条流在中间层做交叉注意力对齐,让模型学会两件事:一是从截图中识别视觉元素的空间位置,二是把控件树中的语义标签和视觉元素关联起来。
对齐训练是整个自研路线的关键。我们需要构造“截图-控件树-语义描述”三元组数据,教模型“这张图上的这个区域,对应控件树中的哪个节点,这个节点的作用是什么”。训练完成后,GUI-Owl 输出的不是一段 text 描述,而是一张UI 语义特征图:每个 UI 元素都被标注了类别、位置、可见性、关键状态以及对应的业务标签。Mobile-Agent-v3 拿到的还是原始截图,而我们的智能体拿到的是已经被业务语义标注过的视觉输入,后续的动作决策自然更准确。
3.3 训练数据构造:比模型结构更花时间的活
自研模型的成本大头不在训练,而在数据。我们花了接近两个月构造 GUI-Owl 的训练数据集,这里面的教训非常多,单独拿出来说一点:公开 GUI 数据集几乎都不适合业务场景。
我们采取的方式是构建“业务 UI 截图 + 结构化标注”生产线。首先用脚本在我们自己的被测 App 上大量截图,覆盖不同页面、不同状态(正常态、空态、加载态、异常态)、不同分辨率(至少 5 种真机尺寸)与不同深色模式开关状态,形成原始截图池。接着把 Appium 自动 dump 出的控件树转成标注信息,作为每个 UI 元素的初始化标签,再做人工校对,修正错误 id、无意义文本、重叠区域的层级关系。
为了让模型学会更鲁棒的定位能力,我们还做了数据增强:随机裁剪、色彩扰动、添加模拟广告遮挡、叠加网络延迟时的半加载状态。这一步特别重要,因为生产环境下测试用例经常在页面未完全渲染时就开始识别,如果训练数据里没有这种“残缺画面”,模型上线后就会在同一类问题上反复翻车。
表格里整理一下吧,我们构造数据时的几个关键比例:
| 数据维度 | 数量/比例 | 备注 |
|---|---|---|
| 原始截图总量 | 约 1.2 万张 | 覆盖 35 个核心页面、4 种状态、5 种分辨率 |
| 双流对齐标注 | 约 9800 条 | 截图区域 + 控件树节点 + 语义描述三元组 |
| 业务标签自定义 | 约 130 个 | 例如"收益卡""风险滑块""协议勾选" |
| 负样本 | 约 1800 条 | 刻意标注遮挡、错位、未加载等异常画面 |
| 数据增强后总量 | 约 4.6 万条 | 用于最终训练输入 |
负样本特别值得说。如果数据里全是“干净、布局完整、渲染正常”的截图,模型很难培养出对异常状态的敏感度。加负样本的目的是教会模型识别“这个区域看不清,不应该点击”或者“页面还在加载中,现在动手会有风险”。这批数据在减少误触方面发挥了决定性作用。
3.4 模型蒸馏与推理服务落地
GUI-Owl 的完整版模型很大,不可能直接跑在测试设备或 CI 集群的每台机器上。我们采用了蒸馏方案:用一个参数量较大的教师模型在业务数据上训练出高精度版本,再蒸馏出一个轻量学生模型(参数量约为教师模型的 18%)用于日常推理。
蒸馏过程中,有两个关键考量必须提一下:一是蒸馏数据的多样性,单纯把训练集原样蒸馏一遍,模型只会死记分布,遇到新页面就失效,我们专门采集了线上用户回放的会话数据来扩充蒸馏集。二是教师模型本身也会有 UI 误识,因此蒸馏前我们加了人工抽检环节,把教师模型的错误输出筛掉再喂给学生模型,防止“AI 教 AI 教出系统性偏见”。
基础设施方面,我们把 GUI-Owl 部署成独立的推理服务,通过 GPU 实例做批量识别。实测单次 UI 语义特征提取的延迟大约在 280 毫秒左右,叠加 Mobile-Agent-v3 的规划耗时,一个完整的任务动作决策在 1.5 秒内可以完成。对于测试执行来说,这样的时延完全可以接受。
4. 两条路线在真实项目里的实测对比与选型判断
4.1 观察指标与测试环境
为了公平评估,我们拆了两组实验环境:对照组直接用 Mobile-Agent-v3 的默认视觉模型 + 智能体框架,实验组使用自研 GUI-Owl 模型替换感知层、保留 Mobile-Agent-v3 的决策框架。被测对象是同一个移动业务 App,测试任务集是 300 条高频业务回归用例,覆盖登录、理财购买流程、风险评估、账户设置、消息中心等核心模块。
设备池使用同一批 8 台 Android 真机,分辨率和系统版本均保持一致,避免设备差异干扰结果。测试周期是两周,每天跑两轮完整回归,收集执行通过率、任务成功率(单条用例从开始到最终验证完成的完整成功比例)、误触率(模型主动执行了错误点击操作的比例)、平均耗时与脚本维护成本变化这几个核心指标。
4.2 实测对比结果
两周测试跑完,数据差异非常明显。对照组 Mobile-Agent-v3 原版的任务成功率约为 74%,这在通用场景下已经算不错了,但放到业务回归的标准里还是不够看——300 条用例有接近四分之一要人工兜底。实验组接入 GUI-Owl 后,任务成功率提升到了 89%,净提升 15 个百分点,主要提升发生在深色模式页面(提升 21 个百分点)和含图表页面的场景(提升 27 个百分点),恰好就是最初发现通用模型乏力的一线场景。
误触率的变化也很有说服力。对照组误触率约为 6.2%,实验组降到了 2.1%。本组数据的意义不只是数字本身,它意味着 CI 夜间回归的报警量大幅度下降——误触往往会在业务环境里产生多余数据,比如不小心把一笔测试订单提交了,这类问题以前每个星期都要手工清理。我们实验期间,实验组的“脏数据清理工时”从每周 2.5 人时降到了 0.5 人时左右。
平均耗时方面,对照组单条任务约 42 秒,实验组约 38 秒。单看绝对值差异不大,但考虑到实验组多做了业务语义分析和验证步骤,这个接近的耗时反而说明 GUI-Owl 的感知效率更优——同样的时间,预算内多做出了更精准的判断。
4.3 两张表的对比整理
再梳理一个直观一点的表格:
| 对比项 | Mobile-Agent-v3 默认路线 | 自研 GUI-Owl + v3 框架 |
|---|---|---|
| 任务成功率 | 74% | 89% |
| 深色模式页面准确率 | 71% | 92% |
| 含图表页面的 UI 识别准确率 | 64% | 91% |
| 误触率 | 6.2% | 2.1% |
| 单条任务平均耗时 | 42s | 38s |
| 业务语义验证能力 | 弱(仅通用描述) | 强(支持业务标签断言) |
| 冷启动成本 | 低(开箱即用) | 高(数据构造 + 训练基础设施) |
| 后续迭代空间 | 依赖项目本体更新 | 可自主沉淀业务数据持续优化 |
这个表格列到“迭代空间”,就是选型问题的核心了。如果你的团队现在需要快速跑通 LLM 驱动自动化,并且业务页面是比较常规的布局(列表、表单、简单按钮组),Mobile-Agent-v3 原版已经够用,冷启动速度决定了这是当前最优解。但如果你像我们一样,业务里有大量动态图表、深色模式、专业术语强依赖的复杂场景,且团队有算法或数据工程的人力储备,自研路线在长期维度上会更值得投入——一次性的数据建设成本换来的是一套可持续演进的感知底座。
4.4 给后来者的三点选型参考
基于这次对比,我总结出三条判断标准,希望对正在决策的团队有帮助。
第一,看业务页面的结构化程度。页面越结构化(表单、列表、设置项),通用模型的优势越大,不需要自研;页面越视觉化(图表、大图展示、自定义绘制控件),自研专用模型带来的增益越明显。
第二,看团队的模型维护能力。自研路线并不仅仅是训练一个模型,还要求团队能持续提供新版本页面的标注数据。具备测试数据管线能力、或者说能够把自动化脚本和标注流程打通,才真正适合自研。否则模型半年不更新,识别退化会非常快。
第三,看失败成本。如果自动化误操作会产生严重的业务副作用(比如提交真实订单、修改线上配置),那模型感知精度的价值就会高于开发成本,值得花钱花时间去换取更低的误触率。反之,自动化只是跑一跑功能冒烟,可以接受少量失败后人工介入,那么开箱即用的方案体验更好。
5. 从 Demo 到全天候巡检:部署落地中的坑和排查链路
5.1 不同分辨率下的坐标漂移问题
最开始我们以为模型输出的坐标是“物理像素坐标”,后来发现实际拿到的是“归一化坐标”。在 1080p 设备上跑通的动作,换到 1440p 设备上,Tap 坐标直接偏移了几十个像素,按钮点偏、点击无效、甚至误触相邻控件的问题集中爆发。
排查过程花了一些时间。第一个燥点是登录页的“确认登录”按钮——在 1080p 设备上坐标稳定命中,切到 1440p 宽屏设备后,模型输出的 Tap 动作落在了按钮左上角大约 12 像素的位置,连续三次没能触发登录。我们开始以为是 GUI-Owl 对宽高比的感知有问题,后来通过打印模型返回的坐标范围和控件树中的真实 bounds 比对才发现,模型输出的是相对屏幕宽高的比例坐标,而执行层直接拿比例值当物理像素用了。
解决方案是在动作映射层加一个坐标空间转换器:把模型输出的归一化坐标乘以当前设备的实际屏幕宽高,再做一次边界裁剪,确保点击点落在目标控件的 bounding box 范围内。这个修复并不复杂,但如果不做,设备池每新增一种分辨率就会出一次问题。同样的转换也要用在 Swipe 动作的起终点上,Pan 手势的变速参数同样需要按设备密度换算。
5.2 广告卡片、弹窗与 Toast 引发的误判链路
这类问题要讲得稍微展开一些,因为排查链路确实非常长。现象是:某条用例在夜间回归里执行到“收益详情页”时,模型误判页面上出现了“新的理财推荐位”,并自动点击了进去,导致后续的所有断言全部失败。
一开始我们怀疑是 GUI-Owl 对不同业务卡片区域的识别能力不够,反复标注数据、重新训练,但问题仍在偶发。后来把失败时刻的截图调出来比对,发现那个“理财推荐位”其实是真实存在的一张运营位广告卡片,只是当天夜里被运营同学替换成了新的视觉素材,颜色和文案变化导致模型认为这是一个“从未见过的新功能入口”。
根因比表面现象更深一层:模型不区分“页面内容变更”和“可交互逻辑变更”。推荐位改了文案和配色,但它的可点击性没有变,用例的预期流程也不要求点击它,模型却把“内容变化”解释为“出现了新任务目标”,从而主动发起了点击。
这个问题的解法分两层。执行层加了一个“任务目标过滤”机制:每步动作前都会把“当前步骤的任务目标”和“模型感知到的新元素”做一次相关性判断,如果新元素不在任务路径上,不允许自动点击,只做记录;感知层继续补充广告卡片类的负样本数据,教模型识别“这是与测试目标无关的运营内容”。修复后,这类误触发下降了七成以上。
5.3 推理延迟优化:从 8 秒压到 2 秒
最初整套链路跑通时,一个简单的三步任务要花接近 8 秒,夜间跑 300 条用例,一跑就是四五个小时,CI 窗口根本扛不住。定位延迟来源时发现,耗时大头是 GUI-Owl 的推理没有做缓存复用——同一个页面在同一轮测试里会被反复截图、反复提取特征,每次都跑一次完整推理。
优化的第一个动作是加截图指纹缓存。对屏幕截图做感知哈希,如果在短时间窗口内(比如 30 秒)碰到相同或接近相同的截图,直接复用上一次的特征提取结果,跳过模型推理。这个优化把页面重复访问场景下的推理次数压缩了接近一半。
第二个动作是动作级别的批处理。原来的链路是一个动作一个推理请求,GUI-Owl 推理一次、Mobile-Agent-v3 又推理一次,两个模型串行执行,每个步骤都要等两轮延迟。我们把 GUI-Owl 的频率降下来,只有在“页面切换或出现异常截图”时才强制重新感知;正常的按钮点击场景直接沿用最近一次的 UI 语义特征图,决策框架只做一次轻量的状态比对。这样调整后,单步动作的决策链路从 1.5 秒左右降到了 0.8 秒,整体任务耗时也顺利控制到了 40 秒以内,全部优化完成后,夜间全量回归的完成时间从 5.2 小时缩短到了 2.1 小时。
5.4 安全护栏:测试数据隔离与敏感页面脱敏
LLM 驱动的自动化有一个容易被忽视的风险:模型的感知数据里可能包含真实用户信息。我们在一次灰度测试中发现,GUI-Owl 会缓存用户中心的截图,里面有明文手机号。这显然不能接受,所以我们在数据链路源头加了脱敏处理。
具体做法是,在截图进入感知模块之前先做一次快速脱敏扫描:对页面中疑似手机号、身份证号、真实姓名的文本区域,执行模糊化遮盖后再交给模型。由于 GUI-Owl 是基于截图输入完成定位的,脱敏并不会影响按钮位置判断,只影响文本内容的识别,对测试流程几乎没有干扰。
此外,我们还为智能体执行任务设置了动作白名单与频率限制:禁止点击“注销账户”“删除资产”“确认转账”等高危入口,同一步骤内的连点次数不能超过 2 次,异常退出超过 3 次时自动中止任务并通知维护人员。这些护栏并不复杂,但它们保证了自动化可以在无人值守的夜间安全运行,也让团队敢把用例量继续往上加。
如果让我回顾这轮从 Mobile-Agent-v3 到 GUI-Owl 自研路线的完整过程,最深的感受是:开源框架解决的是“从 0 到 1”的问题,自研模型解决的是“从 1 到能用”的问题。两者不是互斥的对立方案,而是不同投入阶段的合理选择。真正让方案落地的,不是某一层模型的惊艳表现,而是数据、执行链路、安全护栏和持续标注体系拼凑起来的那张完整的网。最后再补充一点个人体会:自研模型的路线一定不要在项目初期就铺开,先拿 Mobile-Agent-v3 快速验证你的业务场景哪些行、哪些不行,把“不行”的清单攒起来,再决定值不值得投入自研。我们就是这样做的,省掉了大量盲目的重复建设,也让 GUI-Owl 的训练目标从一开始就非常清晰。