☰
ARTEMIS实战:用AI Agent接管Android真机测试
2026/9/28 21:30:30 网站建设 项目流程

1. 真机测试这件事,为什么一直是个老大难

做过 Android 开发的人都有一个共同体会:模拟器跑得再顺,一上真机就可能翻车。厂商定制 ROM 的权限策略、后台保活机制、不同分辨率下的布局错位、系统版本差异导致的 API 行为不一致,这些东西在模拟器里根本复现不出来。所以真机测试从来不是"可选项",而是"必选项"。

但真机测试的痛点也很明显。一台手机从插上 USB 到跑完一轮回归用例,中间要经历安装、授权、点击、输入、截图、日志抓取、异常判定这一长串动作。如果全靠人工,一个中等规模的 App 跑一轮核心流程,少说也要大半天,而且人一累就容易漏点、错点。更麻烦的是,很多团队手里有十几款甚至几十款机型,人工根本铺不开。

Google 开源的 ARTEMIS,瞄准的就是这个场景。它不是又一个 UI 自动化框架,而是一套让 AI Agent 真正"接管"Android 真机测试的完整方案。简单说,它把大模型的决策能力和真机操作能力接在了一起,让 Agent 能像人一样看屏幕、做判断、点按钮、填表单,并且把整个过程记录下来供人复盘。这套东西适合谁?适合已经有一定自动化测试基础、想往智能化方向走的测试开发工程师,也适合想了解 AI Agent 怎么落地到具体硬件场景的开发者。

我花了一段时间把它的思路和实现拆开看了一遍,下面把我理解到的东西完整讲一遍,包括它为什么这么设计、核心环节怎么跑通、以及实操中容易踩的坑。

2. ARTEMIS 的整体设计思路拆解

2.1 它到底解决了传统自动化的哪个死结

传统 Android UI 自动化,无论是基于 UiAutomator 还是 Appium,本质都是"脚本驱动":你提前写好每一步操作,脚本照着执行。这套模式在稳定场景下很好用,但一旦界面变了、弹窗冒出来了、网络慢了导致元素没加载出来,脚本就崩了。维护成本高得吓人,很多团队的自动化用例写完三个月就没人敢动了。

ARTEMIS 的思路换了个方向:不写死每一步,而是给 Agent 一个目标,让它自己看着屏幕决定下一步做什么。比如你告诉它"完成一次登录并进入个人中心",它会自己识别当前在哪个页面、找到输入框、填入账号密码、点击登录、处理可能出现的验证码或弹窗,直到达成目标或者判定失败。

这个转变的关键在于,决策权从"脚本作者"转移到了"模型"。脚本作者只需要描述意图,不需要预判所有分支。这就是 AI Agent 接管测试的核心价值——它把测试用例从"步骤集合"变成了"目标描述"。

2.2 为什么选 MCP 作为连接层

热词里反复出现 MCP,这不是偶然。ARTEMIS 要让 AI Agent 操作真机,中间必须有一层协议把"模型的语言"翻译成"设备的动作"。MCP(Model Context Protocol)在这里扮演的就是这个角色。

打个比方,MCP 就像是 Agent 和设备之间的"插座标准"。Agent 这边不管用的是哪家模型,只要按 MCP 的格式发出请求,另一端的 MCP Server 就负责把它转成具体的设备操作——截屏、点击、滑动、输入文本、读取界面层级。这样做的好处是解耦:模型换了不用改设备层,设备换了也不用改模型层。

我实测下来,这种分层设计最大的收益是可扩展性。你想加一个新能力,比如"读取当前页面的所有可点击元素坐标",只需要在 MCP Server 里加一个工具方法,Agent 那边立刻就能用上,不需要动模型本身。这比把设备操作硬编码进 Agent 逻辑里要干净得多。

2.3 真机连接方式的选择考量

ARTEMIS 支持通过 ADB 连接真机,这是最通用的方式。为什么不用一些厂商提供的专用投屏协议?因为通用性。ADB 几乎在所有 Android 设备上都能用,不需要装额外的厂商工具,也不需要设备开启什么特殊权限(除了 USB 调试)。

当然,ADB 方式也有代价。它的截屏速度受限于adb exec-out screencap的传输效率,在高频操作场景下会有延迟。ARTEMIS 在这方面做了一些优化,比如按需截屏而不是每步都截,以及缓存界面层级信息减少重复查询。这些细节后面会展开讲。

3. 核心组件与关键细节解析

3.1 Agent 的"眼睛":屏幕感知是怎么做的

Agent 要操作真机,第一步是"看见"屏幕。ARTEMIS 的屏幕感知分两层:一层是像素级的截图,一层是结构化的界面层级。

截图好理解,就是通过 ADB 抓一张当前屏幕的 PNG。但光有截图,模型只能做视觉理解,遇到文字密集或者元素重叠的界面就容易判断失误。所以还需要第二层——通过uiautomator dump拿到当前界面的 XML 层级,里面包含了每个控件的类名、文本、坐标、是否可点击等信息。

这两层信息合在一起,Agent 才能既知道"屏幕上长什么样",又知道"哪个位置是可以点的"。我在实际调试时发现,纯靠截图做决策的准确率明显低于截图加层级信息的组合,尤其是在表单填写这种需要精确定位输入框的场景。

注意:uiautomator dump在某些定制 ROM 上会被限制,如果拿不到层级信息,需要退回到纯视觉方案,这时候模型的视觉理解能力就变得很关键。

3.2 Agent 的"手":操作指令怎么下发

操作指令这块,ARTEMIS 通过 MCP Server 暴露了一组标准工具,常见的有:

工具名称作用底层实现
tap点击指定坐标adb shell input tap x y
swipe滑动adb shell input swipe x1 y1 x2 y2 duration
input_text输入文本adb shell input text或 ADBKeyboard
screenshot截屏adb exec-out screencap -p
dump_ui获取界面层级adb shell uiautomator dump
launch_app启动应用adb shell am start
press_key按键adb shell input keyevent

这里有个细节值得说:输入文本用adb shell input text有个坑,它不支持中文和特殊字符。所以实际项目里通常会装一个 ADBKeyboard 输入法,通过广播的方式把文本送进去。ARTEMIS 的实现在这块做了兼容处理,会根据文本内容自动选择输入方式。

3.3 决策循环:Agent 是怎么"想"的

Agent 的核心是一个循环:观察 → 思考 → 行动 → 再观察。每一轮,它把当前屏幕状态(截图加层级)和任务目标一起发给模型,模型返回下一步该做什么,MCP Server 执行,然后进入下一轮。

这个循环看起来简单,但有几个关键设计点:

第一是上下文管理。如果每一轮都把完整历史塞给模型,token 消耗会爆炸。ARTEMIS 的做法是保留最近若干轮的操作记录,加上当前屏幕状态,更早的历史做摘要压缩。这样既保留了决策所需的上下文,又控制了成本。

第二是终止条件。Agent 不能无限循环下去,必须能判断"任务完成了"或者"卡住了"。完成判定通常靠界面特征匹配,比如检测到目标页面的某个标志性元素。卡住判定则靠重复操作检测——如果连续几轮都在点同一个位置且界面没变化,就判定失败并退出。

第三是错误恢复。真机上什么意外都可能发生:突然来个系统弹窗、应用崩溃了、网络断了。Agent 需要能识别这些异常并尝试恢复,比如关掉弹窗、重启应用。这部分逻辑 ARTEMIS 是通过在提示词里明确告诉模型"遇到 X 情况应该怎么做"来实现的。

3.4 任务描述怎么写才靠谱

这是我在实操中体会最深的一点:Agent 的能力上限,很大程度上取决于你怎么描述任务。

写得太粗,比如"测试登录功能",Agent 不知道具体要验证什么,可能随便点两下就报告完成了。写得太细,比如"点击坐标 (540, 1200),等待 2 秒,输入 admin",那又退回到脚本模式了,失去了 Agent 的意义。

比较合适的粒度是目标加约束。比如:"使用账号 admin、密码 123456 完成登录,登录成功后应进入首页并显示用户名。如果出现权限弹窗,选择允许。如果登录失败,记录错误提示文本。"

这种描述既给了 Agent 明确的成功标准,又留出了让它自己处理分支的空间。我一般会建议团队把测试用例改写成这种"意图描述"的形式,这本身就是个梳理测试逻辑的好过程。

4. 从零跑通一套 ARTEMIS 真机测试

4.1 环境准备与依赖安装

先把基础环境搭起来。需要的东西不多,但版本要对。

  • Android SDK Platform Tools:主要是要里面的 adb,版本建议 34 以上
  • Python 3.10+:ARTEMIS 的 MCP Server 和 Agent 逻辑主要用 Python 写
  • 一台开启 USB 调试的真机:设置 → 关于手机 → 连点版本号七次 → 开发者选项 → USB 调试
  • 一个可用的模型 API:Agent 的决策依赖大模型,需要配置对应的 key

装依赖的时候有个坑,uiautomator相关的 Python 包在不同系统上依赖的底层库不一样,Linux 上一般没问题,Windows 上可能需要额外装 Visual C++ 运行库。我建议直接用虚拟环境隔离,避免污染系统 Python。

python -m venv artemis-env source artemis-env/bin/activate # Windows 用 artemis-env\Scripts\activate pip install -r requirements.txt

4.2 设备连接与验证

设备连上后,先确认 adb 能识别:

adb devices

正常应该输出类似:

List of devices attached ABCD1234 device

如果显示unauthorized,说明手机上还没确认 USB 调试授权,看下手机屏幕有没有弹窗,点允许。如果显示offline,试试adb kill-server && adb start-server重启一下服务。

验证截屏和层级获取是否正常:

adb exec-out screencap -p > test.png adb shell uiautomator dump /sdcard/ui.xml adb pull /sdcard/ui.xml .

这三条命令能跑通,说明设备侧的准备就到位了。我遇到过某些机型uiautomator dump报错的情况,通常是系统权限限制,换个机型或者用 root 权限能解决。

4.3 MCP Server 的配置与启动

MCP Server 是 Agent 和设备之间的桥梁,配置重点是告诉它用哪个设备、暴露哪些工具。

配置文件一般长这样:

{ "device_serial": "ABCD1234", "tools": ["tap", "swipe", "input_text", "screenshot", "dump_ui", "launch_app"], "screenshot_format": "png", "ui_dump_timeout": 5000 }

device_serial在多设备场景下很重要,不指定的话 adb 会随机选一台,导致操作跑到别的设备上去。ui_dump_timeout我一般设 5 秒,太短了容易在慢设备上超时,太长了卡住的时候等得难受。

启动 Server:

python -m artemis.mcp_server --config config.json

启动成功后会监听一个本地端口,Agent 通过这个端口发指令。我习惯启动后先用一个简单的 tap 测试一下链路通不通,确认没问题再跑完整任务。

4.4 编写第一个 Agent 任务

任务定义通常是一个 YAML 或者 JSON,描述目标和约束:

task: 登录并验证首页 app: com.example.myapp steps: - 启动应用 - 如果出现隐私协议弹窗,点击同意 - 在登录页输入账号 admin 和密码 123456 - 点击登录按钮 - 验证是否进入首页,首页应包含"欢迎"字样 success_criteria: - 界面出现"欢迎"文本 failure_criteria: - 界面出现"密码错误"文本 - 连续 3 轮操作界面无变化 max_rounds: 20

max_rounds是安全阀,防止 Agent 陷入死循环烧 token。我一般设 15 到 25 之间,具体看任务复杂度。

4.5 运行与观察

启动 Agent:

python -m artemis.agent --task login_task.yaml

运行过程中,Agent 每一轮的决策和操作都会打日志。我强烈建议第一次跑的时候把日志级别调到 DEBUG,把每轮的截图也存下来。这样出问题的时候能回放整个决策过程,看清楚 Agent 是在哪一步走偏的。

一个典型的成功日志大概是这样:

Round 1: 观察到登录页,决策:输入账号 Round 2: 观察到账号已填,决策:输入密码 Round 3: 观察到密码已填,决策:点击登录 Round 4: 观察到首页,检测到"欢迎"文本,任务成功

如果看到 Round 5、Round 6 还在重复同样的操作,那基本就是卡住了,需要去看截图分析原因。

5. 实操中踩过的坑与排查技巧

5.1 常见问题速查表

现象可能原因排查方向
Agent 一直点同一个位置界面没变化,模型误判看截图确认是否真的没响应,检查点击坐标是否被状态栏遮挡
输入文本乱码中文或特殊字符切换到 ADBKeyboard 输入法
截屏超时设备性能差或 USB 连接不稳降低截屏频率,换 USB 口或数据线
层级信息为空定制 ROM 限制改用纯视觉方案,或换测试机型
任务提前判定成功成功条件太宽松收紧 success_criteria,加更多特征校验
token 消耗过快上下文太长减少历史轮数,压缩截图分辨率

5.2 几个我踩过的具体坑

坑一:状态栏和导航栏干扰点击。有些机型的状态栏会盖住顶部内容,Agent 按层级信息算出来的坐标点上去,实际点到了状态栏。解决办法是在 dump_ui 之后过滤掉状态栏和导航栏区域的元素,或者在配置里指定可操作区域的范围。

坑二:动画导致截图时机不对。页面切换有动画,Agent 在动画进行中截屏,拿到的是一张模糊的中间态,模型判断就容易出错。我的做法是在每次操作后加一个短暂的稳定等待,或者检测界面层级连续两次一致再认为稳定。

坑三:模型对相似界面区分不清。比如登录页和注册页长得很像,模型可能搞混。这时候在任务描述里加上更明确的特征,比如"登录页标题是'登录',注册页标题是'注册'",能显著提升准确率。

坑四:多设备并发时的资源竞争。如果同时跑多个 Agent 操作多台设备,adb server 可能成为瓶颈。建议给每台设备分配独立的 adb server 端口,或者用 adb 的-s参数明确指定设备序列号。

5.3 提升稳定性的几个实操心得

第一,给 Agent 加"确认"步骤。在关键操作后,让 Agent 先确认界面变化再继续下一步,而不是盲目往下走。这能大幅减少连锁错误。

第二,失败重试要有策略。不是简单重试,而是重试前先做一次"复位"——回到应用首页或者重启应用,从干净状态重新开始。

第三,把高频操作固化成工具。比如"登录"这个动作在很多用例里都要用,与其让 Agent 每次都重新决策,不如封装成一个 MCP 工具,Agent 直接调用。这样既快又稳。

第四,定期回放失败案例。我每周会挑几个失败的用例,把日志和截图拿出来复盘,看看是模型判断问题还是环境问题。积累下来会发现很多问题是重复的,针对性优化后成功率能提升不少。

6. 这套方案适合什么样的团队

ARTEMIS 这套思路不是万能的。如果你的测试用例非常稳定、界面几乎不变,那传统脚本自动化成本更低、速度更快。但如果你的应用迭代快、界面经常调整、机型覆盖广,那 Agent 方案的优势就体现出来了——它不需要你为每个界面变化去改脚本。

我个人觉得最适合的切入方式是:先用 Agent 跑那些"流程长、分支多、人工维护脚本成本高"的用例,比如注册登录、下单支付、多步骤表单填写。这些场景传统脚本最容易崩,而 Agent 的容错能力正好能补上。等跑顺了,再逐步扩大范围。

另外提醒一句,Agent 方案对模型能力有依赖,模型换了效果可能波动。所以生产环境用的时候,建议固定模型版本,并且建立一套回归机制,模型升级前先跑一遍基准用例,确认成功率没下降再切。

最后分享一个小技巧:如果你想让 Agent 的表现更稳定,可以在任务描述里给它一些"领域知识"。比如告诉它"这个应用的登录按钮通常在页面底部,文字是'立即登录'",这种先验信息能显著减少它的试错次数。这本质上是在用提示词给模型补上下文,成本很低但效果明显。

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

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

立即咨询