UI Automator:定义、关键概念及其工作原理

作者: IT Sectr 发布日期: 2026-04-08 阅读时间: 8 分钟

UI Automator 是 Google 推出的用于 Android 应用程序自动化 UI 测试的框架,它在系统级别运行,并且可以与单个应用程序之外的用户界面元素进行交互。与 Espresso 不同,UI Automator 不依赖于特定应用程序的进程:它可以打开系统对话框、通知面板并在应用程序之间切换。根据 Google Android Developers,UI Automator 使用标准的 Accessibility Service 来访问设备的 UI 树。

要点

  • UI Automator — 用于 Android 跨应用程序 UI 测试的框架。
  • UiDevice — 访问设备屏幕及其元素的入口点。
  • UiSelector — 根据文本、类、描述和层次结构搜索元素的机制。
  • Cross-application — 测试可以在 Settings、Browser 和被测应用程序之间切换。
  • Accessibility Service — UI Automator 使用它来读取和操作 UI 树。

什么是 UI Automator?

UI Automator 是一个用于 Android 功能性 UI 测试的框架,它在操作系统级别运行。它提供 API 来访问设备屏幕上的任何元素,无论它属于哪个应用程序 — 包括系统状态栏、权限对话框、主屏幕和第三方应用程序。这使得它对于测试超出单个应用程序范围的场景不可或缺。

在架构上,UI Automator 使用 Accessibility Service — 与 TalkBack、Switch Access 和其他无障碍工具使用的相同的服务。通过此服务,框架获取当前屏幕的完整 UI 组件树,并允许对它们执行操作:点击、滑动、文本输入、长按。

UI Automator 首次出现在 Android 4.3(API 18)中,此后一直是 Android Testing Support Library 的一部分,作为 Google 官方跨应用程序测试工具。在 AndroidX Test 中,它作为一个独立的工件 androidx.test.uiautomator:uiautomator 版本 2.3.0(2024)提供,支持从 API 18 开始的所有 Android 版本。

UI Automator 的工作原理

UI Automator 的工作原理 基于扫描当前屏幕的 Accessibility 树。当调用 findObject(selector) 方法时,框架遍历 View 层次结构,找到第一个满足 UiSelector 条件的元素,并返回一个 UiObject 对象 — 用于与真实 View 交互的代理。

UI Automator 测试的生命周期

一个典型的 UI Automator 测试从获取 UiDevice 实例开始,该实例代表物理设备。UiDevice 提供用于搜索元素、管理按钮按下(Home、Back、Recent)、旋转屏幕和截图的方法。通过 UiSelector 找到元素后,在 UiObject 上执行操作。

基本示例

在下面的示例中,测试打开 Settings 应用程序,通过文本找到 “电池” 项目并点击它。UI Automator 不需要启动 Activity — 它可以与设备的任何屏幕一起使用,包括第三方应用程序。

kotlin
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

// 打开设置屏幕
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("设置")), 2000)

// 找到 “电池” 项目并点击
val batteryItem = device.findObject(
    UiSelector().text("电池")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)

UiDevice 和 UiSelector:关键类

UiDevice — 与设备交互的主要类。它提供用于搜索元素、模拟硬件按钮按下(Home、Back、Menu、Volume)、电源管理、截图和等待特定屏幕状态的方法。UiDevice 每个测试创建一次,并重复用于所有操作。

UiSelector — 是一个用于搜索 UI 元素的流畅 API。与 Espresso 中的 ViewMatchers 不同,UiSelector 不需要编译 — 搜索条件通过方法链形成:text()className()description()resourceId()index()。多个条件通过逻辑 AND 自动组合。

UiSelector 方法用途
text(String)根据元素的精确文本搜索
textContains(String)根据部分文本搜索
resourceId(String)根据资源 ID 搜索(例如 com.example:id/button)
className(String)根据 View 的类名搜索
description(String)根据 content-description 搜索
childSelector(selector)在容器中搜索子元素

多条件搜索示例

当屏幕上有多个具有相同文本的元素时,UiSelector 允许组合条件:根据 ID 找到容器,然后在其中 — 根据文本和类找到元素。这保证了所需组件的唯一标识。childSelector 方法将搜索区域缩小到指定的容器,从而加快 UI 树中的导航。

kotlin
val scrollView = device.findObject(
    UiSelector().resourceId("android:id/list")
)

// 在列表中找到带有 “Wi-Fi” 文本的元素
val wifiItem = scrollView.findObject(
    UiSelector().text("Wi-Fi")
wifiItem.click()

使用 UI Automator 进行跨应用程序测试

跨应用程序(跨应用)测试 — 选择 UI Automator 的主要原因。该框架可以在应用程序之间切换,通过浏览器测试 OAuth 登录,检查系统对话框(权限、应用程序选择),并与系统状态栏、通知面板和锁定屏幕进行交互。

测试 OAuth 登录

一个典型的跨应用测试场景:应用程序打开浏览器进行 OAuth 授权,用户输入用户名和密码,浏览器重定向回应用程序。UI Automator 在进程之间切换,在浏览器中找到输入字段,填写它们,然后点击 “登录”。

kotlin
// 等待浏览器出现
device.wait(Until.hasObject(
    UiSelector().packageName("com.android.chrome")
), 5000)

// 在浏览器中搜索电子邮件输入字段
val emailField = device.findObject(
    UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"

检查系统对话框

UI Automator 可以检查并关闭系统对话框 — 地理位置权限、通知、文件访问。这对于测试应用程序的首次启动至关重要,因为系统会顺序请求多个权限。没有 UI Automator,此类场景无法自动化,因为系统对话框不属于应用程序的进程。

UI Automator vs Espresso:方法比较

选择 UI Automator 和 Espresso 之间的选择取决于测试场景。Espresso 针对单个应用程序的测试进行了优化,具有自动同步和最少的样板代码。UI Automator 适用于需要与系统、浏览器或多个应用程序交互的场景。

标准UI AutomatorEspresso
范围整个设备,多个应用程序单个应用程序
同步手动(wait, sleep)自动(Idling Resource)
速度较慢(通过服务访问)较快(在进程内运行)
系统 UI支持(Notifications, Quick Settings)不支持
搜索精度基于属性的 UiSelector基于类型和层次结构的 ViewMatchers
稳定性较低(取决于时间)较高(自动等待)

在实践中,这些框架通常一起使用:Espresso 以高稳定性覆盖主要应用程序的 UI 测试,而 UI Automator 则用于超出应用程序范围的场景 — OAuth 登录、系统权限、使用 Share Intent。这种组合以最小的测试维护成本提供了最大的 UI 覆盖。

在 Android 项目中配置 UI Automator

连接 UI Automator 是通过在 build.gradle 中添加依赖项来完成的。该框架是 AndroidX Test 的一部分,不需要在清单中声明额外权限 — 对 Accessibility Service 的访问在仪器测试启动时自动配置。

Gradle 依赖

最小配置包括 uiautomator 工件和标准的测试运行器 AndroidJUnitRunner。UI Automator 测试放置在 src/androidTest 目录中,并在具有 Android API 18+ 的模拟器或物理设备上运行。

kotlin
dependencies {
    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
    androidTestImplementation("androidx.test.ext:junit:1.2.1")
    androidTestImplementation("androidx.test:runner:1.6.1")
}

UiDevice 和测试配置

要获取 UiDevice 实例,请使用 InstrumentationRegistry.getInstrumentation()。UiDevice 应在 setUp() 方法中创建一次,并在类的所有测试中重复使用以节省设备资源。需要注意的是,UiDevice 不是线程安全的 — 所有操作必须在测试方法的单个线程中执行。在每个测试中创建新的 UiDevice 会导致开销和执行速度减慢。建议在 beforeClass 方法中创建一次 UiDevice,并为测试类的所有测试重复使用它。

UI Automator 中的等待

与 Espresso 不同,UI Automator 没有自动同步。要等待元素出现,请使用 UiDevice.wait(condition, timeout) 方法配合 Until 对象:Until.findObject(selector)、Until.hasObject(selector)、Until.gone(selector)。没有正确的等待,测试会因竞态条件而不稳定 — 元素可能无法在搜索时出现在屏幕上。建议设置至少 3-5 秒的超时时间以确保稳定性。

常见问题

UI Automator 与 Espresso 有何不同?

UI Automator 在 Accessibility Service 级别运行,可以与任何应用程序交互。Espresso 在单个应用程序的进程内运行,并使用与 UI 线程的自动同步。UI Automator 更适合跨应用场景,Espresso — 更适合单个应用程序的稳定测试。

UI Automator 可以在任何设备上运行吗?

是的,UI Automator 适用于所有具有 Android API 18+ 的设备。它不需要 root 访问权限 — 使用标准的 Accessibility Service,该服务在测试启动时通过 Instrumentation 激活。

UI Automator 如何找到屏幕上的元素?

UI Automator 使用 Accessibility Service 获取当前屏幕的完整 UI 组件树。然后 UiSelector 遍历此树,并根据给定的条件找到元素:文本、类、ID、content-description 或其组合。

UI Automator 支持截图吗?

是的,UiDevice.takeScreenshot(storePath) 方法可以截取当前屏幕的屏幕截图并保存到文件中。这对于调试很有用:当测试失败时,可以保存屏幕截图并分析屏幕状态。

为什么 UI Automator 测试有时会无缘无故失败?

UI Automator 没有自动同步,因此测试对时序敏感。如果动画尚未完成或 View 尚未渲染,findObject 可能找不到元素。解决方案 — 使用具有足够超时的 UiDevice.wait()

总结

UI Automator 工具集涵盖了所有关键跨应用测试场景,是系统级 Android 自动化的标准。

  • UI Automator — 通过 Accessibility Service 进行跨应用 Android 测试的框架。
  • UiDevice — 访问设备和屏幕元素的入口点。
  • UiSelector — 用于根据文本、ID、类和层次结构搜索元素的流畅 API。
  • 跨应用测试 — OAuth 登录、系统权限、与多个应用程序的交互。
  • 与 Espresso 比较 — UI Automator 覆盖范围更广,但在稳定性和速度上不如。
  • 等待 — 为了保证测试稳定性,必须使用 UiDevice.wait() 和 Until 条件。
  • API 18+ — 框架支持从 Android 4.3 开始的所有设备。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读