之前介绍过最好用的 Flutter AI 测试框架,然后有很多人在问有没有原生平台的,刚好就看到了一个原生平台的开源测试框架 agent-device ,甚至它还支持鸿蒙:

agent-device 是专门为 AI Agent 设计的设备自动化 CLI 工具 ,可以类比 Vercel 的 agent-browser 是给 AI 用的浏览器自动化工具那样,agent-device 是给 AI 用的 App 准备的标准化通道,例如:

agent-device apps --platform ios
agent-device open <app> --platform ios
agent-device snapshot -i
agent-device press @e12
agent-device diff snapshot -i
agent-device close

比如这里的 snapshot -i ,它会把当前 UI 转成 Agent 更容易理解的结构化树,同时给可交互元素生成 @e1@e2 这种引用。

它最核心的能力是不用截图去识别控件agent-device 是通过检查真实 App UI,输出无障碍访问树(accessibility snapshot),然后将 UI 中的可交互元素映射为短引用(@e1, @e2, @e3),让 AI 知道屏幕上有什么:

agent-device snapshot -i
# @e1 [heading] "Settings"
# @e2 [button] "Sign In"
# @e3 [text-field] "Email"

这样 AI 就可以直接用 @e3 操作 「[text-field] "Email"」,不需要自己去读坐标,也不需要每次截图分析,同时功能上支持:

  • 截图:用于 debug/回放

  • 视频录制(record):录制操作流程

  • 日志(logs):app 日志流

  • 网络流量(network):HTTP 请求抓包

  • 性能采样(perf):CPU/内存

  • 崩溃上下文:crash 时的现场信息

甚至它还支持工作流回放,将 AI 探索过的交互录制成 .ad 脚本,然后可以在 CI、本地、重复场景中回放执行,等效于 e2e 测试用例。

agent-device 的场景其实就是:Agent 写代码,之后安装到对应设备,然后 agent-device 打开 App ,通过 snapshot 读取当前 UI 结构,之后 Agent 根据 @e1 / @e2 / selector 操作 UI ,然后得到 「截图 / 录屏 / 日志 / 网络 / 性能」等证据存档,最后再让 Agent 根据测试结果修复问题。

当然,最最最最重要的是它是多平台支持:

  • iOS 真机/Simulator(XCTest 驱动)

  • Android Emulator / 真机(ADB 驱动)

  • tvOS / Android TV

  • macOS App

  • Linux (AT-SPI)

  • HarmonyOS (HDC 驱动)

整个流程大概如下图所示:

如果拆开来看,整个架构大概如下:

  • Session 模型 :先 open 一个设备会话,后续所有命令在这个 session 上下文内执行(锁住设备资源、保持状态)

  • Daemon 架构 :后台运行一个长驻进程(daemon),CLI 命令通过 IPC 与 daemon 通信

  • 提升效率 :snapshot 使用无障碍树而不是视觉截图,让 AI 用最少 token 获取 UI 信息;-i(interactive only)进一步只返回可交互元素,而且截图测试的方式是真的死慢

  • 语义引用系统 (Refs):@e1~@eN 是每次 snapshot 后分配的临时引用,命令可直接用 ref 而不是坐标,降低 AI 犯错概率,比如坐标在滚动后就失效,但 ref 是语义感知的

  • Interactor 模式 :每个平台实现一个统一的 Interactor 接口(tap, swipe, snapshot, screenshot...),核心调度层面对接口编程,平台差异被隔离在各自的 platforms/ 目录

  • 可控范围src/core/capabilities.ts 给每条命令定义哪些平台/设备类型支持,防止 AI 调用不支持的命令,会在 admission 阶段直接报错而不是无意义地发送到设备

当然,也存在一些平台限制,例如:

局限 具体表现
pinch/rotate 手势 仅支持 iOS Simulator + Android,HarmonyOS 不支持 pinch/rotate
read(文本识别) 只支持 iOS/Android
logs/network/perf HarmonyOS 均不支持
clipboard HarmonyOS 需要 app-level 授权,读写均可能失败
权限管理 HarmonyOS 仅支持 grant,deny/reset 未实现

然后在平台链路上,每个平台都有自己一套实现,从代码看,你会看到一套非常复杂的工作流程。

iOS 体系

首先是 iOS,iOS 核心用的还是我们熟悉的 XCTest Runner ,iOS 本身没有开放的 UI 自动化 API 给外部进程用,这里agent-device 的做法是:

在目标设备上动态构建并运行一个 XCTest bundle(.xctestrun),通过 XCTest 框架的 XCUITest 能力操控 UI,然后在这个 Runner 进程和 CLI 之间建立 TCP 通信通道。

更具体的结构是:

  • runner-xctestrun.ts :动态生成 .xctestrun 配置文件(相当于 Xcode 的测试 scheme)、构建参数、signing 配置

  • runner-session.ts :管理 Runner 进程的生命周期,启动 xcodebuild test-without-building、等待 ready、保持 session 热启动

  • runner-transport.ts :TCP 通信层,发送 JSON 命令到 Runner,接收响应,超时/重连处理

  • runner-client.ts :命令执行的上层入口,完整的故障恢复逻辑

  • runner-contract.ts :Runner 通信协议定义,命令类型枚举

  • interactions.ts :将 tap/swipe/type 等抽象命令翻译为 Runner 命令

  • xml.ts :解析 XCTest 返回的 Accessibility XML 快照

  • simctl.ts :调用 xcrun simctl 操作模拟器(boot/shutdown/install)

  • devicectl.ts : 调用 Xcode 15+ 的 xcrun devicectl 操作真机

  • perf.ts :通过 xcodebuild + Instruments XML 采集性能数据(CPU/内存/帧率)

这里最有意思的就是Runner 故障恢复机制,由于 XCTest Runner 是一个独立进程,TCP 通信可能在命令执行过程中断(网络抖动、Runner 崩溃),所以项目设计了一套 lifecycle 状态机

  • 每个命令发出前打上唯一 commandId

  • 如果传输中断,发送 status 命令查询该 commandId 的状态

  • 根据 lifecycleState 决策:

    • completed(已完成):从 lifecycleResponseJson 取结果,session 保留

    • failed(已失败):抛出 Runner 报告的错误,session 保留

    • accepted/started(仍在飞行中): 抛 in-flight 错误,session 保留

    • 未知状态 : 保守路径:invalidate session,重新启动

比如 CLI 发出了一个 tap 命令,TCP 连接中途断了,CLI 根本不知道 Runner 是否已经执行了这个 tap,如果重试可能会 double-tap ,但是如果不重试,可能 tap 根本没发生,这时候就需要通过 lifecycle 判断。

另外 macOS 和 iOS 共用了一套后端,所以逻辑基本可以复用,另外截图功能上也是做了很多细节处理,比如:

状态栏内容覆盖,将时间/电量伪造为固定值,让截图更容易区分。

Android

Android 平台就是 ADB + 自定义 Snapshot Helper APK ,类似 iOS 的 Runner transport,只是 Android 的走的是 adb 命令(adb shelladb exec-outadb install 等):

  • 本地 adb -s <serial> 直连

  • Provider 注入模式(可以支持云端/远程 Android 设备)

  • 文本注入 provider 覆盖(用于非 ASCII 字符)

Android 平台最有意思的就是双引擎架构快照实现

为什么需要自定义 Helper APK?因为 Android 原生的 uiautomator dump 有严重缺陷:

  • 经常超时(UI 繁忙时 hang 住)

  • 返回的节点数有限,无法获取完整 can-scroll-forward/backward 属性

  • 不支持多窗口

所以 agent-device 开发了一个 android-snapshot-helper APK(项目根目录有独立子包),通过 Android Instrumentation 框架运行,能返回更完整和稳定的 UI 树 XML,同时它还维护了一个 persistent session(长驻后台进程),避免每次快照都 cold start ,比如:

  • snapshot-helper-install.ts : 检测版本/安装 APK

  • snapshot-helper-session.ts :长驻 session 管理

  • snapshot-helper-capture.ts :通过 instrumentation 调用获取 XML

另外一个就是滚动内容提示,这个也挺有意思,Android 快照时,agent-device 会额外执行 adb shell dumpsys activity top,从 Activity 状态中推断每个 ScrollView/RecyclerView 是否还有隐藏内容(上方/下方),然后标注到节点上,让 AI 知道「这个列表下面还有更多内容」。

Linux

Linux 平台用的就是AT-SPI2(Assistive Technology Service Provider Interface)+ Python 桥 ,之前 agent-device 也尝试过 node-gtk(Node.js 原生绑定),但 ABI 不兼容、CI 编译问题太多,所以现在改用 Python3 + python3-gi(PyGObject)调用 AT-SPI2,Node.js 负责启动 Python 子进程、读取 JSON 输。

AT-SPI2 是 Linux 桌面辅助功能标准(GNOME/KDE 等都支持),类似 macOS 的 Accessibility API,每个 GTK/Qt 窗口会把自己的 UI 树注册到 D-Bus 上,通过 AT-SPI2 可以遍历所有应用的 UI 节点。

鸿蒙

最后鸿蒙平台主要通过 HDC 链路来适配 ,可以类比 Android 的 ADB,HarmonyOS 使用的是 hdc 命令行工具,核心是 runHarmonyHdc(device, args) 会自动带上 -t <serial> 设备序列号,与 ADB 的用法完全镜像。

UI 快照层 ArkUI Hierarchy(等价于 iOS 的 XCTest / Android 的 ViewHierarchy) ,比如 hdc shell uitest dumpLayout -p /data/local/tmp/xxx.json ,最终得到 @e1, @e2... 等节点,最重要的是他还出来了鸿蒙本身的一个问题兼容:

uitest uiRecord 卡死时 dumpLayout 会 hang,所以项目加了预检,发现 stuck 进程时直接报错提示 reboot。

所以鸿蒙的 snapshot 是通过 uitest dumpLayout 生成 ArkUI component tree,然后支持 interactiveOnlycompactdepthscoperaw 模式,同时通过 snapshot_display 进行截图。

还有一些有意思的,比如 Alert 识别(纯 ArkUI 节点分析),不像 iOS 有原生的 alert API,HarmonyOS 的弹窗是普通 ArkUI 组件,所以 agent-device 是通过关键词匹配识别弹窗并提取按钮坐标,同时支持中英文按钮文本(确定/取消/允许/拒绝/知道了...):

if (type.includes('dialog') || type.includes('alert') || 
    label.includes('暂无可用打开方式') || label.includes('权限') ...) {
  // 识别为弹窗,提取 buttons
}

最后

对比 Appium、Detox、Maestro 这些传统 mobile automation framework, agent-device 是为 AI Agent 优化的,更适合 AI 自动化测试,当然它对人写的场景就不是很友好了,如果真要对比,我理解是:

  • Appium / Detox / Maestro: 支持人写,重点是稳定、可维护、CI 回归

  • agent-device:面向 AI Agent 现场探索、验证、debug、采证、沉淀 replay

目前看起来它还不是特别适合大规模的稳定回归测试,一些复杂 UI 的测试也还不够稳定,所以它更适合作用 Agent 开发过程中的实时反馈和修复支持,让 Agent 改完代码后自己跑起来看、自己点、自己截图、自己抓日志,然后基于真实结果继续修,而且支持原生跨平台,最重要是,开源,免费,MIT。

链接

https://github.com/callstack/agent-device

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐