做了两年以上 Android 自动化的人,大概率都经历过这种时刻:凌晨两点 CI 挂了,你爬起来翻日志,发现只是登录按钮从resource-id改成了text,整个脚本报废。维护成本高、跑起来慢、UI 一动就崩,这类痛点逼着测试团队不断在框架层做文章,但始终绕不过一个根本问题——脚本是人写出来的,它只认死理,不认意图。所以当 Google 把 ARTEMIS 开源的消息放出来的时候,我第一反应是:这次可能真的不一样了。
ARTEMIS 走的是另一条路:不再由人写清楚每一步点击什么、输入什么,而是告诉 AI Agent 一个目标,让它像人一样盯着屏幕,自己思考下一步做什么,操作完再观察反馈,错了再改。整个流程跑在真实 Android 设备上,用的也是真实 UI、真实网络、真实弹窗。这篇东西我会从传统自动化的死穴开始聊,拆解 ARTEMIS 的感知、推理、执行机制,再把我在本地复现时踩过的坑和总结出的经验一并放出来,最后聊几句这个工具到底适合谁、怎么落进现有测试体系。
1. 为什么 LLM 要接管真机测试:传统自动化的死穴在哪
1.1 脚本式自动化的维护成本是被低估的
很多团队上自动化测试,目标都是“减少重复劳动”,但真实情况往往是:自动化刚上线时很爽,跑了几周之后,一小半时间都花在修脚本上。为什么?因为 UI 测试的本质是断言“当前屏幕状态是否符合预期”,而传统脚本描述状态的方式极其脆弱——resource-id、xpath、坐标偏移、控件层级,任何一个前端改动都可能让这些定位器全部失效。
我在一个中型应用上做过统计:一次常规的界面改版,牵扯到 80 多个用例,其中 30 多个需要手工调整定位器。每个用例平均 30 分钟,这就是 15 个小时的维护量。这种成本让很多人得出一个结论:自动化不适合探索性测试和冒烟测试,只适合核心流程的回归保护。这话没错,但也说明了一个事实——传统工具链的瓶颈不在执行,而在“描述”本身太机械。
ARTEMIS 想解决的就是这个描述问题。它不是通过定位器去匹配控件,而是通过视觉语言模型去“看”截图,理解界面上有什么,再根据任务目标决定操作。脚本时代,你告诉计算机“点击 id 为 login_btn 的按钮”;AI Agent 时代,你告诉模型“登录”,它自己找到那个按钮。
1.2 任务描述取代步骤描述:测试用例的范式变化
传统用例写的是“行为步骤”,每一步都是确定的,执行顺序也是确定的。而 AI 驱动的测试用例写的是“目标”,从起点到终点的路径由模型自行规划。
举一个非常简单的例子:
传统用例大概是这个写法:
# 打开设置 driver.find_element(By.XPATH, "//android.widget.TextView[@text='设置']").click() # 点进关于手机 driver.find_element(By.XPATH, "//android.widget.TextView[@text='关于手机']").click() # 读取版本号 version = driver.find_element(By.XPATH, "//android.widget.TextView[contains(@text, 'Android')]").text如果是 ARTEMIS 风格,你写的更像是:
任务:打开设置中的“关于手机”页面,读出 Android 版本号并返回。前者是命令,后者是意图。意图不需要关心按钮在哪一层、控件叫什么名字,只关心最终结果。这意味着同一个任务可以在不同型号、不同分辨率、不同系统版本的真机上运行,因为 Agent 每走一步都会“重新看一遍屏幕”再决策,而不是盲人摸象式地执行固定步骤。
1.3 ARTEMIS 在测试工具链里到底处于什么位置
横向对比一下现有的工具,能更清楚 ARTEMIS 的定位:
| 方案类型 | 代表工具 | 核心依赖 | 主要缺点 |
|---|---|---|---|
| 自动化测试框架 | Appium、Espresso | 代码定位控件 | 维护成本高、UI 变更敏感 |
| 云端真机平台 | Firebase Test Lab、Sauce Labs | 预定义脚本 | 同样依赖脚本质量 |
| 无脚本 RPA 式方案 | 部分商用工具 | 录制回放 | 识别能力弱,不稳定 |
| LLM 驱动测试代理 | ARTEMIS、A3、AppAgent | 视觉语言模型 + 真机控制 | 推理延迟和 token 成本较高 |
ARTEMIS 属于最下面这一类。它的价值不是替代你需要跑的 1000 个回归用例,而是接住那些“脚本写起来不划算、纯手工又太费人”的长尾场景——新功能的探索性测试、覆盖面广但不需要精确断言的冒烟测试、以及真机兼容性验证。
2. ARTEMIS 内部机制拆解:视觉感知、任务推理与动作执行
2.1 感知层:截图加布局树的双源输入
ARTEMIS 要像人一样操作手机,第一件事是“看”。它的感知层会同时拉两个来源的信息:
一是像素级的屏幕截图,这是给视觉语言模型看的,模型可以判断按钮位置、图片状态、布局是否错乱。二是 Android 系统的视图层级树(类似 UI Automator dump 出来的 XML),这相当于给 Agent 一个“辅助线”,让它知道页面元素的层级关系、文本内容、控件类型。
这两套信息是互补的。纯截图的问题是像素坐标不稳定,同一按钮在不同分辨率下坐标完全不一样;纯布局树的问题是信息量大且冗余,很多节点根本没有视觉意义,而且截图里能看出的“图片加载失败”这类问题,布局树完全无法表达。ARTEMIS 把两者结合,先让视觉模型描述图像内容,再用布局树提取可操作的控件结构,最终生成带有坐标信息的操作候选列表。
我在复现运行的时候发现,这类 Agent 对布局树的质量要求其实很高。如果设备开启了某些开发者选项(比如“显示布局边界”),截图会出现大量额外线条,会明显干扰模型的判断。这一点后面实测部分会详细说。
2.2 推理层:任务拆解与动作空间约束
拿到感知结果之后,进入 LLM 的推理阶段。ARTEMIS 在推理层做的核心工作是三件事:
第一,把最终任务拆成可执行的子步骤。任务目标是“帮我把壁纸换成默认的”,模型需要理解这是“设置 → 壁纸 → 选择默认壁纸”的多步流程,而不是一步点击。
第二,在当前屏幕状态下选择动作。动作空间是受限的,模型只能从预定义的动作类型里挑,主要包括:
tap(x, y):点击屏幕坐标long_text/input_text:输入文本swipe(x1, y1, x2, y2, duration):滑动back():返回键home():回桌面enter():确认键
限制动作空间非常重要。如果不加限制,让模型自由输出 Python 代码直接调 API,理论上很强,但实际会变得完全不可控——模型生成代码的错误率太高了,而且你没法直观地跟踪它在干什么。反而是这种简洁的坐标动作集,配合“观察-行动-反馈”循环,每一步都可追踪、可复现,出了错也能排查。
第三,判断任务是否完成。模型每一步之后都会问自己“任务达到目标了吗”,这个判断不是靠比对预期结果,而是靠视觉和布局信息比对当前状态,比如“是否已经进入了关于手机页面”“版本号是否已经出现”。
2.3 执行层:ADB 链路与真机控制
推理层只是“想”,真正“做”要通过 Android 的底层控制链路。ARTEMIS 在真机上执行的本质还是 ADB 指令加系统事件注入,这也是它能跑真实设备的原因。
典型的执行链路是:
LLM 推理出动作 → 生成 ADB 或 ViewServer 指令 → 注入触摸/文本事件 → 等待页面刷新 → 重新截图并获取布局树 → 反馈给模型这里有个细节:一些类似的 Agent 项目会选择用无障碍服务(AccessibilityService)注入事件,因为无障碍事件可以拿到更多系统级别的反馈,而且能处理一些普通 ADB 注入搞不定的场景(比如输入中文)。ARTEMIS 的好处是它的抽象层做得比较干净,无论底层走 ADB 还是无障碍,对外动作格式是一致的。对于像我这样的测试工程师,这意味着不用去深入 Android 注入机制的细节,把精力放在任务设计和结果验证上。
2.4 反射机制:错了能回头,才是 Agent 和脚本的本质区别
如果 Agent 点了某个按钮,页面没有如期变化,怎么办?脚本的做法是直接报错,人去看日志。ARTEMIS 的做法是触发一轮反思:当前页面状态和预期不符,是点击没生效,还是点错了位置?它会把新截图和布局树再喂给模型,让模型重新判断,并换一种操作方式继续尝试。
这个“反射机制”是整个系统最关键的设计。任务越复杂、界面越动态,第一次尝试就越容易失败。ARTEMIS 之所以能跑通多步任务,靠的不是模型每一步都判断正确,而是它允许出错、并能在错之后自我修正。
在配置里能看到一个类似max_steps的参数,控制单个任务的最大执行步数。设置太大,任务会陷入无意义的重复操作;设置太小,稍微绕一点的任务就跑不完。我在实测中习惯先给目标任务设一个预计步数再乘以 1.5,比如预计 5 步的任务设 8 步,宁可给了余量再观察实际执行情况。
3. 从零跑通 ARTEMIS:环境准备与首个 Agent 驱动用例
3.1 环境准备清单
ARTEMIS 这类 LLM 驱动的测试工具,环境要求大体分三块:模型侧、设备侧、运行环境侧。下面这个清单是基于我在复现中的通用实践整理的,不同版本可能略有差异:
| 项目 | 推荐配置 | 说明 |
|---|---|---|
| Python | 3.10 或更高 | 依赖较多,太老的版本容易出包冲突 |
| Android 设备 | 真机优先,Android 10 以上 | 模拟器也可以,但部分场景模拟器行为不真实 |
| ADB | Android SDK Platform-Tools 最新版 | 必须能通过adb devices看到设备 |
| 视觉语言模型 | 支持图像输入的 LLM 接口 | 截图理解依赖 VLM 能力 |
| 运行环境 | 本地命令行或 CI Runner | 只需要 Python 环境,不需要安装 AS |
这里要特别强调一句:真机比模拟器重要。ARTEMIS 的卖点就是跑真实设备,如果你一直在模拟器上试,会错过很多真机特有的问题——系统弹窗、网络切换、性能波动、厂商定制 UI,这些才是真机测试的价值所在。
3.2 设备侧准备与 ADB 前置检查
连接设备之前,先做几项准备,能省掉后面一大堆麻烦:
- 开启开发者选项和 USB 调试。
- 把“屏幕常亮”打开,锁屏时间设为“无”或很久。否则 Agent 跑到一半屏幕灭了,感知层的截图就是一整块黑,模型直接蒙圈。
- 关闭所有可能干扰的浮窗和引导层。建议先关掉“显示触摸操作”“显示布局边界”这类开发者选项,它们会在截图上叠加视觉噪音,影响模型判断。
adb devices确认设备已被识别,状态是device而不是unauthorized。- 在手机上弹窗确认 USB 调试授权。
如果你是第一次连这台设备,插上 USB 之后手机会弹出“允许 USB 调试吗”,一定要点确认并且勾选“始终允许”,否则后面 Agent 启动时拿不到设备权限很痛苦。
3.3 定义任务与首次运行
环境没问题之后,就可以定义任务了。我建议第一个用例不要选太复杂的,选一个 3 到 5 步能完成的界面上操作,既能验证链路又不会因为任务太绕而分不清是模型问题还是环境问题。
我当时用的第一个任务是:
{ "task": "在设置里找到“关于手机”页面,返回 Android 版本号。", "app_launch": "settings", "max_steps": 8 }启动服务,等待 Agent 完成。整个过程的日志大概分成几个阶段:初始化设备、感知当前界面、模型推理下一步、执行动作、重新感知、循环直到任务完成或者步数用尽。第一次跑的时候,我的经验是不要干等,打开另一个终端,实时adb logcat看设备侧日志,因为有些动作看起来执行了,但应用内部其实报了错或者跳到了别的页面,这些信息设备日志里都有。
3.4 任务输出与结果验证
Agent 完成任务后,除了返回最终结果,还会给出执行轨迹。这个轨迹很关键,它是一份自动生成的“AI 测试记录”,包含每一步的截图、动作、思考理由。你可以拿它来做两件事:
第一,判断 Agent 走的路径是不是合理。AI 往往会找到一条人想不到的路径,这很正常,只要最终结果正确就可以接受。第二,沉淀成回归测试的参考基线。跑一次没问题不算稳定,同一个任务跑三次,看路径和执行时间波动大不大。
验证结果本身也有讲究。比如“返回 Android 版本号”这个任务,我一开始只让 Agent 输出文本,结果它读出来的值是13,我核对了一下真机是 Android 14,差点以为模型识别错了。再一查,原来应用内显示的是“Android 版本”那一栏的 API Level 对应名称,不同厂商的定制系统显示规则完全不同。这个小乌龙提醒我:任务目标里依赖的“预期值”,最好用视觉模型能直接判断的东西,比如“屏幕上出现‘Android 版本’且下方有字母数字”,而不是指定一个具体版本号。
4. 实测中的坑与边界:AI 真机测试真正难在哪
4.1 坐标依赖性问题比想象中严重
LLM 驱动的 Agent 虽然不用写死 xpath,但它输出的动作最终依然是屏幕坐标。这就带来一个新问题:同一块屏幕,换一台分辨率不同的设备,Agent 上一次学到的坐标就完全失效。
我实测过两个任务,在 Pixel 上跑得好好的,换到一台国产定制机上(同 Android 版本、不同分辨率),点击位置直接偏了,点到了隔壁的列表项。ARTEMIS 本身有一定容错(因为它每步都重新感知),但这种容错上限不高,如果首次点击位置偏得太多,交互的对象就完全不对了。
想彻底解决这个问题,目前比较实用的思路是按设备规格建任务基线:
- 同一型号同一分辨率的设备,共享同一套 Agent 任务配置。
- 不同分辨率的设备,单独跑一次任务预热,让 Agent 重新适应坐标。
- 分辨率差异特别大的设备,考虑有没有必要纳入同一套自动化体系。
这个问题的本质是:AI 替代了“人和控件的映射”,但没有替代“设备和坐标的映射”。它依然是测试链路上的一环,工程化时要把设备分组这件事接住。
4.2 系统弹窗与权限请求是最大的流程破坏者
跑真机自动化的人都知道,最烦的不是被测应用本身,而是系统弹窗:权限请求、系统更新提示、后台应用通知、某厂商的“安全中心”提醒。这些弹窗随机出现,脚本时代靠代码预判,但弹窗类型和出现时机根本无法穷举。
ARTEMIS 对弹窗有天然的容错能力——模型看到弹窗会把它当成页面的一部分,然后判断“要不要关掉它”。但这不等于万事大吉。
我遇到的最典型场景是:Agent 在设置里打开权限管理,手机弹出了“允许设置在此设备上通话吗?”,模型选择了点击“允许”,这是对的。但下一次运行同一个任务时,弹窗没有出现,模型依旧按“上次的经验”去找那个按钮,找不到就开始瞎试,连点好几个错误位置,最后步数耗尽。
面对这种情况,我现在的处理方式是:在任务开始前人为清理弹窗状态,或者把“允许/拒绝”这类系统级交互尽量做成前置条件而非任务内步骤。简单说,让 Agent 做业务路径的探索,不做系统级弹窗的稳定操作,因为后者的状态依赖太强。
4.3 状态变化的误判:按钮置灰与加载等待
很多任务卡在同一个地方:AI 看到页面有个按钮,点了,但按钮其实是置灰状态,点击没有触发任何效果。模型再观察页面,发现“什么都没有变”,于是反射机制启动,换个位置再点一次,又没反应,步数耗尽。
这种情况在传统脚本里很好处理,一条等待条件就搞定了。在 AI 测试里反而不容易,因为“等待”不是 Agent 擅长的事,它的每个动作间隔是固定的,感知到的都是瞬时状态,不会主动去等一个元素变成可点击。
我的缓解方案是两条:
- 在任务描述里明确写出中间判断的等待条件,比如“如果页面显示加载中,先等待加载完成再继续”。
- 通过设备侧的设置,关闭动画缩放(窗口动画、过渡动画、动画时长缩放都设为关闭)。这能让页面状态切换更干脆,减少“更新中”“加载中”这类中间态出现的频率。
4.4 任务目标不明确直接导致死循环
这里要说一个很反直觉但极其重要的问题:AI Agent 对“模棱两可”的容忍度很低。人操作手机时,如果任务目标是“打开微信设置”,人会快速在杂乱的界面里找到入口;但 AI 面对同样模糊的任务,会在所有看似相关的位置都试一遍,然后陷入循环。
有个失败案例让我印象很深:任务目标是“把手机亮度调到最低”,Agent 进入设置后,在“显示”页面点了亮度条,没反应;又去“屏幕与亮度”里找了一个看似相关的滑动条,划了一下,又没反应;然后回到“显示”页面,再点亮度条……如此往复,直到步数耗尽。
问题不在模型能力,而在任务描述缺少明确的终止条件。正确写法应该是:“把屏幕亮度调整到系统允许的最低值,最终确认亮度条已到最左端且未触发系统调暗保护。”给 Agent 一个可验证的终态,它能知道自己什么时候算完成,而不是一直在“尝试-观察-再尝试”的循环里空转。
任务描述三原则我用下来很管用:
- 目标必须可视觉验证,而不是“感觉差不多”。
- 路径可以有分支,但终态必须有明确画面。
- 不要同时塞多个子任务,拆开跑成功率和排查难度都会更好。
4.5 Token 成本与执行耗时要揉进方案里
AI 真机测试不是免费的。每一步操作,都要发一张截图和一份布局树给模型推理,跑一个 8 步任务,光模型调用就 8 次以上,失败重试的话更多。设备越多、任务越复杂,成本线性上升。
我在本地做过一个粗略估算:
| 任务复杂度 | 平均步数 | 预计模型调用次数 | 单个任务耗时(分钟级) |
|---|---|---|---|
| 简单(3步内) | 3 | 5 次左右 | 1-2 |
| 中等(5-8步) | 6 | 10 次左右 | 3-5 |
| 复杂(10步以上) | 12 | 20 次以上 | 8-15 |
这个耗时比传统脚本慢得多,比人工也快不了太多。所以 ARTEMIS 现阶段不适合做高频回归,适合做“少量、高价值、路径灵活”的真机验证:比如发布前的关键流程探索、多型号真机的兼容性检查、以及那些脚本维护成本远高于执行成本的长尾用例。
5. 把 ARTEMIS 接进现有测试体系的实际建议
5.1 先用它补探索性测试的缺口
大多数测试团队的传统分工是:自动化脚本负责回归,手工测试负责探索。探索性测试的问题在于完全依赖人的随机性和经验,测过就忘,没留下记录。ARTEMIS 在这里是个很好的补充:让 Agent 跑一些目标宽泛的探索任务,它会留下完整的截图和操作轨迹,等于给“探索”装了个回放功能。
我在实际团队里推的时候,第一个落地的场景是“新版本适配检查”:任务描述为“进入应用首页,浏览主要功能区,尝试打开至少三个不同业务模块,记录每个模块是否正常显示”,然后让 Agent 在三台不同型号的真机上跑。它跑出来的截图和日志归档后,版本适配的置信度比之前手点快了不少,而且能复现“当时屏幕上到底发生了什么”。
5.2 与现有自动化框架共存,不是取代
从名字就能看出来,ARTEMIS 解决的是“让 Agent 像人一样操作手机”的问题,它跟 Espresso、Appium 根本不是同一个层面的东西。Espresso 是应用内白盒测试,能直接拿到 Activity、View 的状态,执行快、断言强,这类场景 ARTEMIS 永远替代不了。Appium 覆盖面广,生态成熟,适合大量可复用的跨平台脚本。
合理的分层是:
- 核心高频回归:继续用脚本框架,跑得快、断言准。
- 长尾探索与适配验证:交给 ARTEMIS 这类 AI Agent,成本可控且能覆盖脚本写不完的路径。
- 灰盒深度测试:仍然需要 instrumentation 类的工具介入。
5.3 测试工程师需要补的两项新能力
AI Agent 测试普及之后,测试工程师的核心技能会从“写定位器”转向“写任务描述和理解 Agent 行为”。我自己体会下来,有两项能力最值得刻意练习:
一是任务设计能力。同一个人,任务写得模糊还是精确,Agent 的成功率差距是数量级的。学会把业务目标转译成“视觉上可验证的终态”,是 AI 测试时代的基本功。
二是日志与轨迹的分析能力。Agent 执行出错,不会像脚本失败一样甩给你一个AssertionError,而是留下一长串“感知—推理—行动”的记录。你需要从这些记录里判断问题出在感知(看错了)、推理(想错了)还是执行(做了但没生效),这种分诊能力在以后会越来越值钱。
5.4 给想上手的人一个最低成本路径
如果你看完想自己试一把,我建议按这个顺序推进:
- 先不用管多复杂的功能,让 Agent 跑通一个“打开应用 → 进入某个二级页面 → 截图返回”的最短链路,验证环境没问题。
- 再试一个带输入动作的任务,比如“在搜索框输入关键词并查看搜索结果”,锻炼模型对输入框的理解。
- 然后试一个会失败的任务,故意让它点一个不存在的按钮,亲眼看看反射机制是怎么“犯错—发现—修正”的。
- 最后才上真实的业务用例,并且从小任务开始积累自己的任务描述模板。
另外一个小提示:如果你拿的是高分辨率真机(比如 2K 屏),截图尺寸会很大,发给模型的时候注意接口的图片大小限制,必要时先做缩放预处理。这个问题的表现就是:小屏设备跑得好好的,一上高分辨率设备就频繁超时或报错,但日志里没有任何 UI 操作失败的痕迹。
ARTEMIS 这类工具的潜力不在于多智能,而在于它第一次让测试工作的重心从“描述过程”回归到了“描述结果”。对我来说,这种转换带来的最大解放感是:我终于不用在凌晨两点,因为一个按钮改了 id 而爬起来写补丁了。