Android 测试框架 —— UI Automator
介绍
UI Automator 是 Google 在 Android 4.1 的时候推出的 Android UI 自动化测试框架。 它可以模拟用户操作(比如:点击、滑动、输入文本等)和获取应用程序的界面信息,帮助开发者构建可靠且高效的自动化测试脚本。
特点和优势
与其他的测试框架相比,UI Automator 具有以下这些特点和优势:
- 跨应用程序测试:UI Automator 可以跨应用程序进行自动化测试,可以获取和操作整个设备上的界面元素,而不仅仅局限于单个应用程序。
- 强大的界面元素查找能力:UI Automator 提供了丰富的 API 和机制来查找应用程序界面上的元素,可以根据属性、文本、ID 等条件进行准确的查找。
- 多种用户操作模拟:UI Automator 支持模拟用户的各种操作,如点击、滑动、长按、输入文本等,可以实现复杂的用户交互行为。
- 多设备支持:UI Automator 可以同时连接多个设备,并在这些设备上执行自动化测试。
- 异步任务处理:UI Automator 支持处理异步任务,可以等待应用程序加载完成或响应操作完成后再进行下一步操作。
- 丰富的日志和报告:UI Automator 提供了详细的日志和报告功能,可以帮助开发者定位问题、分析测试结果。
应用场景
下面是 UI Automator 的一些常见应用场景:
- 自动化测试:UI Automator 可以用于开发和执行自动化测试脚本,帮助开发者检测应用程序的功能、性能和稳定性。它可以自动模拟用户操作,执行各种测试用例,并生成详细的测试报告。
- UI 自动化验证:UI Automator 可以用于验证应用程序的用户界面是否正确显示和响应。它可以通过查找元素、获取属性和模拟用户操作来验证应用程序的界面元素、布局和交互逻辑。
- 多应用程序测试:UI Automator 可以跨应用程序进行测试,对多个应用程序的功能和集成进行验证。它可以在不同的应用程序之间切换,模拟用户在多个应用程序之间的操作和交互。
- 兼容性测试:UI Automator 可以在不同的设备和 Android 版本上执行自动化测试,帮助开发者确保应用程序在各种环境下的兼容性。它可以在多个真机和模拟器上运行测试用例,验证应用程序在不同设备上的表现。
- 性能测试:UI Automator 可以测量应用程序的性能指标,如启动时间、响应时间和内存占用等。它可以自动执行一系列操作和操作,并记录关键性能数据,以评估应用程序的性能表现。
- 用户体验测试:UI Automator 可以模拟用户的真实操作和使用场景,评估应用程序的用户体验。它可以模拟用户的滑动、点击、输入等操作,测试应用程序在不同用户交互情况下的响应和流畅度。
Warning
UI Automator 对于 WebView 构建的应用适配不是很好。
1.0 vs 2.0
UI Automator 主要版本有 1.0 和 2.0,现在大多使用的是 2.0 版本。可通过 UI Automator 官网 查看版本的变更历史。
类型 | 1.0 | 2.0 |
---|---|---|
实现语言 | Java | Java |
框架实现 | 基于 Instrumentation 框架实现 | 基于 Android 的 AccessibilityService 实现 |
支持范围 | 单应用 | 跨应用 |
API 功能 | 提供了一组用于模拟用户操作和获取界面元素信息的 API,如点击、滑动、查找元素等 | 在 1.0 的基础功能上进行了扩展,提供更多强大的 API 和功能,如通过 UISelector 搜索元素、设置忽略的控件、处理异步任务等。 |
兼容性 | Android 4.1 及以上版本的设备上运行 | Android 5.0 及以上的版本运行,相比1.0 版本,2.0 的兼容性更好 |
快速入门
安装 Android Studio
下载并安装 Android Studio。
创建一个项目
在 Android Studio 中,androidTest
和 test
是两个常见的目录,它们分别用于不同类型的测试:
androidTest
:这个目录用于编写 Android UI 测试,通常用于运行 Instrumentation Tests(仪器化测试)。这些测试是针对 Android 应用的 UI 和功能进行的,依赖于 Android 设备或模拟器;test
:这个目录用于编写 本地单元测试,这些测试通常是在本地 JVM 上运行的,与 Android 框架无关。它们用于测试 Java 或 Kotlin 代码的逻辑部分,而不涉及 UI 或设备相关的功能。
找到 build.gradle(Module :app)
添加依赖:
dependencies {
...
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.3.0-alpha03'
}
编写测试用例
我们以 com.example.uiautomatordemo
作为项目包名,在 androidTest
目录下创建一个 Demo.java
文件用于开发 UI 测试:
app
├── java
│ ├── com.example.uiautomatordemo
│ ├── com.example.uiautomatordemo(androidTest)
│ │ └── Demo.java
│ └── com.example.uiautomatordemo(test)
这个例子中,我们以找到桌面的 Gmail 应用,让 UI Automator 打开这个测试应用:
@RunWith(AndroidJUnit4.class)
public class Demo {
@Test
public void openGmail() {
// 创建一个 Device 对象,然后先返回桌面
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
device.pressHome();
// 从桌面上找到 Gmail 应用图标,然后点击
UiObject2 gmail = device.findObject(By.text("Gmail"));
Boolean opened = gmail.clickAndWait(Until.newWindow(), 3000);
assertTrue(opened);
}
}
编写完成后,点击 Android Studio 的运行按钮,可以看到 Gmail 应用启动了。
Warning
测试设备使用的是谷歌的原生机器,使用其他的机器,需要根据机器的应用和布局挑选出合适的应用。
核心类
UI Automator 提供了相关 API 文档 ,可以查询到常用的接口和核心类。
UiDevice
UiDevice
是 UI Automator 中的非常重要的类,用于与设备进行交互,模拟用户行为,以及访问设备的各种 UI 元素。UI
Automator 允许开发人员编写测试脚本,通过模拟点击、滑动、输入文本等操作来验证应用程序的行为。
在使用 UiDevice
前,需要通过 UiDevice.getInstance()
获取先初始化 UiDevice
:
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
当获取到 UiDevice
后,就可以获取到设备的信息和操作设备了:
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 获取屏幕尺寸
DisplayMetrics metrics = new DisplayMetrics();
device.getDisplayMetrics(metrics);
// 获取系统版本
String osVersion = device.getSystemVersion();
// 点击屏幕某个位置坐标
device.click(x, y);
// 滑动和滚动:其中 startX, startY 是滑动的起点坐标,endX, endY 是终点坐标,steps 是滑动的步数
device.swipe(startX, startY, endX, endY, steps);
// 滚动操作(在一个滚动视图中)
UiObject scrollable = device.findObject(new UiSelector().scrollable(true));
scrollable.scrollForward(); // 向前滚动
// 输入文本
UiObject editText = device.findObject(new UiSelector().className("android.widget.EditText"));
editText.setText("Hello, world!");
// 按键操作
// 按 Home 键:
device.pressHome();
// 按返回键:
device.pressBack();
// 按菜单键:
device.pressMenu();
// 按电源键:
device.pressPower();
// 获取设备屏幕截图:
File screenshot = new File("/path/to/save/screenshot.png");
device.takeScreenshot(screenshot);
// UiDevice 提供了等待方法,以确保 UI 元素在交互之前是可见的:
UiObject myButton = device.findObject(new UiSelector().text("Click me"));
myButton.waitForExists(5000); // 等待最多 5 秒钟,直到按钮存在
UI 自动化测试依赖于页面加载的速度和UI元素的可见性。在查找元素时,使用 waitForExists()
或者 waitForSelector()
等方法来确保元素已经加载。同时,在自动化测试中,设备可能会锁屏,导致 UiDevice
无法操作。可以在测试开始时确保设备解锁:
if (!device.isScreenOn()) {
device.wakeUp();
}
在一些设备上,可能需要授予应用程序特定的权限(如读取联系人、存储权限等)。在自动化测试中,确保权限已经授权,或者在测试中模拟用户授权。
查找元素
在 UI Automator 中,查找界面的元素的方式有以下三种:
- 使用
UiSelector
查找元素。UiSelector
是 UI Automator 原生方法。 - 使用
BySelector
查找元素。BySelector
将UiSelector
的方法进行一次封装,使得查找元素更加方便。 - 使用
By
查找元素。By
是对BySelector
的再次封装和简化,两者的 API 基本相同。
Quota
谷歌对 By
和 BySelector
的解释:
By is a utility class which enables the creation of BySelectors in a concise manner.
Its primary function is to provide static factory methods for constructing BySelectors using a shortened syntax. For
example, you would use findObject(By.text("foo"))
rather than findObject(new BySelector().text("foo"))
to select UI
elements with the text value "foo".
UiSelector
UiSelector
是 UI Automator 中的一个类,用于查找 Android 设备上的 UI 元素(如按钮、文本框、列表项等)。通过使用 UiSelector
搜索出符合要求的 UI 元素,然后与之进行交互(如点击、输入文本、检查文本等)。
// 通过文本查找
UiSelector selector = new UiSelector().text("Hello");
// 通过资源 ID 查找
UiSelector selector = new UiSelector().resourceId("com.example.app:id/button1");
// 通过类名查找
UiSelector selector = new UiSelector().className("android.widget.Button");
// 通过描述查找
UiSelector selector = new UiSelector().description("Submit");
// 通过父元素查找
UiSelector selector = new UiSelector().childSelector(new UiSelector().text("Next"));
// 查找启用状态为 true 的控件
UiSelector selector = new UiSelector().enabled(true);
// 查找可点击的控件
UiSelector selector = new UiSelector().clickable(true);
// 根据控件在父容器中的位置查找
UiSelector selector = new UiSelector().index(1); // 查找父容器中第2个元素
// 查找包含特定文本的控件
UiSelector selector = new UiSelector().textContains("Submit");
// 使用正则表达式匹配文本内容
UiSelector selector = new UiSelector().textMatches(".*Submit.*");
// 查找具有指定坐标范围的控件。
UiSelector selector = new UiSelector().bounds("[0,0][100,100]");
通常,UiSelector
查找到的控件会与 UiDevice
的 findObject
方法结合使用,完成点击等动作:
UiSelector selector = new UiSelector().text("Next").clickable(true);
UiObject nextButton = device.findObject(selector);
nextButton.click();
Note
如果找不到符合条件的 UI 元素,UiObject
的相关方法可能会抛出 UiObjectNotFoundException
。可以使用 exists()
等方法检查元素是否存在,或者通过 waitForExists()
等方法添加等待机制。
BySelector
在 UiSelector
的基础上,BySelector
对其所有的方法进行了一次封装,使得查找元素更加方便。
BySelector selector = new BySelector().text("foo");
UiObject foo = device.findObject(selector);
foo.click();
Warning
在最新版本的 UI Automator 上,BySelector
的构造方法标记了:
Clients should not instanciate this class directly. Use the
By
factory class instead.
谷歌推荐使用 By
方法代替 BySelector
。
By
在 UiSelector
的基础上,By
对 BySelector
再进行了一次封装。经过封装后的 By
缩短了 BySelector
的语法,提供了静态工厂方法来构造
BySelector
对象。
BySelector selector = By.text("foo");
UiObject foo = device.findObject(selector);
foo.click();
通过查看 By.text()
方法的实现,可以看到 By.text()
是对 BySelector
的一层封装。
public static @NonNull BySelector text(@NonNull String text) {
return new BySelector().text(text);
}
UiObject
使用 UiSelector
或者 By
等方式,筛选出界面上的元素,再通过 UiDevice
执行查找操作后,返回的是一个 UiObject
对象。
UiObject
是 UI Automator 中用于表示和操作单个 UI 元素的类。通过 UiObject
,可以与 UI 元素进行交互,如点击、输入文本、检查属性等。
// 获取 UiDevice 实例
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 使用 UiSelector 查找一个文本为 "Submit" 的按钮,点击按钮
UiObject button = device.findObject(new UiSelector().text("Submit"));
button.click();
// 输入文本
UiObject editText = device.findObject(new UiSelector().className("android.widget.EditText"));
editText.setText("Hello, UI Automator!"); // 输入文本
// 获取文本内容
String text = button.getText();
// 获取元素的类名
String className = button.getClassName();
// 获取元素的类名
if (button.exists()) {
// 元素存在,可以继续操作
} else {
// 元素不存在
}
// 长按按钮
button.longClick();
// 滑动操作
UiObject scrollableList = device.findObject(new UiSelector().className("android.widget.ListView"));
scrollableList.scrollForward(); // 向前滚动
UiObject2
UiObject2
是 UI Automator 2.0 引入的新类,它是 UiObject
的升级版本,具有更多功能和更好的性能支持。UiObject2
对比
UiObject
提供了更高效的 UI 元素查找和操作,尤其是在涉及复杂的布局和动态更新的界面时,UiObject2
显得更加高效和稳定。同时,
UiObject2
引入了基于 By
的查找方式,支持更灵活的定位方式,能够更快速地找到 UI 元素。
特性 | UiObject |
UiObject2 |
---|---|---|
引入版本 | UI Automator 1.x | UI Automator 2.0 |
查找方式 | 基于 UiSelector ,支持简单查找方式 |
基于 By ,支持多种查找方式,如 By.text() 、By.desc() 等 |
性能 | 相对较低,处理复杂布局时性能较差 | 性能较高,特别适用于复杂和动态更新的界面 |
支持视图 | 适用于简单 UI 元素操作 | 支持复杂视图,如 RecyclerView 、ListView 等 |
交互方式 | 基本的交互操作,如点击、输入文本等 | 更丰富的交互方式,支持更多UI组件操作 |
高级功能 | 功能较为基础,操作简单 | 支持更复杂的操作,如手势操作、元素滚动等 |
等待机制 | 提供基本的等待方法,如 waitForExists() |
提供更强大的等待机制,支持更复杂的等待操作 |
容错性 | 对动态界面的容错能力较差 | 对动态界面和大量元素的操作更为稳定 |
UiObject2
的使用方式和 UiObject
基本相同,不同的是在使用完 findObject()
方法后,返回的是一个 UiObject2
对象:
// 获取 UiDevice 实例
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 使用 By 查找一个按钮
UiObject2 button = device.findObject(By.text("Submit"));
UiCollection
UiCollection
是 UI Automator 2.0 提供的一种用于处理多个 UI 元素的集合的类。与 UiObject
和 UiObject2
聚焦于单一 UI
元素的操作不同,UiCollection
主要用于操作一个元素集合,它允许访问和操作一组 UI 元素,如 RecyclerView
, ListView
,
GridView
等。UiCollection
和 UiObject2
配合使用时,可以更方便地操作复杂的界面组件, 例如在一个可滚动列表中查找多个元素,
或是对多个 RecyclerView
项进行操作。
// 获取 UiDevice 实例
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 查找一个包含多个项的集合
UiCollection recyclerView = device.findObject(By.clazz("androidx.recyclerview.widget.RecyclerView"));
// 遍历集合中的所有元素
UiCollection recyclerView = device.findObject(By.clazz("androidx.recyclerview.widget.RecyclerView"));
// 获取子元素的数量
int count = recyclerView.getChildCount();
if (count == 0) {
Log.d("RecyclerView", "No items found");
}
// 遍历 RecyclerView 中的所有项
int itemCount = recyclerView.getChildCount();
for (int i = 0; i < itemCount; i++) {
UiObject2 item = recyclerView.getChild(i); // 获取第 i 项
String text = item.getText(); // 获取每一项的文本
Log.d("Item Text", text);
}
// 向下滚动 RecyclerView
recyclerView.scroll(Direction.DOWN, 1.0f); // 向下滚动
// 获取 RecyclerView 中的第一个子项
UiObject2 firstItem = recyclerView.getChild(0);
// 点击第一个子项
firstItem.click();
UiScrollable
UiScrollable
是 UI Automator 中用于处理滚动操作的类。它通常与 UiCollection
一起使用,尤其是在需要滚动并交互的长列表或其他可滚动容器中。
UiScrollable
提供了方法来滚动到特定的位置、元素或方向,帮助模拟用户在长列表或分页界面中的滚动操作。
UiScrollable
支持向上、向下、向左、向右滚动,可以滚动到包含特定文本或特定属性的元素。在滚动的过程中,支持调整滚动的速度和步数。
UiScrollable scrollable = new UiScrollable(By.className("androidx.recyclerview.widget.RecyclerView"));
// 向下滚动内容直到找到某个元素:
scrollable.scrollTextIntoView("Target Item");
// 滚动指定的距离或到达指定的元素:
scrollable.scrollForward(); // 向下滚动一页
scrollable.scrollBackward(); // 向上滚动一页
scrollable.scroll(Direction.DOWN, 1.0f); // 滚动一定比例,1.0f 表示滚动满屏
// 滚动并点击某个特定的元素:
UiObject2 targetItem = scrollable.getChild(By.text("Target Item"));
targetItem.click();
条件
Condition
是 UI Automator 中用于等待某些条件满足的机制。在动态加载或界面变化的场景中,Condition
可以帮助实现更为可靠的同步,避免因界面更新未完成而引发的错误。相比传统的自动化测试方法通常使用 Thread.sleep()
来等待一段固定时间,
,使用 Condition
,只有在满足特定条件时才会继续执行,不会浪费不必要的时间。Condition
可以理解为
“等待条件”,它在某个条件达成以前不会执行后续的操作。例如,等待某个按钮可点击,或等待一个加载动画消失;等待某个按钮可点击或者等待一个加载动画消失。
Condition
是一个接口类,具体的实现类有 UiObject2Condition
和 SearchCondition
:
UiObject2Condition
用于检查UiObject2
的状态。通常,两者结合使用。SearchCondition
代表满足一定条件的,需要查找的 UI 元素,主要用于判断是否存在某个组件。
另外一个条件是 EventCondition
。EventCondition
是指依赖于某个事件或一系列事件已经发生的条件。EventCondition
也是一个抽象类,
它实现的不是 Condition
接口,而是 UiAutomation.AccessibilityEventFilter
接口。
UiObject2Condition
UiObject2Condition
是一个条件类,用于定义某个 UI 对象(如按钮、文本框、列表项等)在特定情况下的状态。该类的作用是等待某个 UI
元素满足某些特定条件,以便进行下一步的操作。例如,它可以用来等待某个 UI 元素可见、启用或者可点击等。通常这种条件检查在自动化测试中非常有用,特别是在
UI 测试场景中,确保元素准备好再进行交互。
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
BySelector selector = By.text("foo");
UiObject2 foo = device.findObject(selector);
// 等待控件的字体发生变化,变成成 `Hello World`
UiObject2Condition<Boolean> condition = new UiObject2Condition<>() {
@Override
public Boolean apply(UiObject2 args) {
return Objects.equals(args.getText(), "Hello World");
}
};
// UiObject2Condition 和 UiObject2 一同使用
foo.wait(condition, 1000);
SearchCondition
SearchCondition
主要用于描述查找某个 UI 元素时需要满足的条件。它可以包含一组条件判断,只有当这些条件都被满足时,才会认为查找的
UI 元素是符合要求的。通常,SearchCondition
不可以单独使用,因为 SearchCondition
的接口方法 Searchable
是一个保护的方法,外部无法直接初始化。
SearchCondition<Boolean> searchCondition = new SearchCondition<Boolean>() {
@Override
public Boolean apply(Searchable args) { // Searchable 会报无法找到的错误
return null;
}
};
SearchCondition
的初始化一般会通过 Until
类进行。在 Until
类中,定义了很多返回值为 SearchCondition
的静态方法:
public static SearchCondition<Boolean> gone(@NonNull BySelector selector) {}
public static SearchCondition<Boolean> hasObject(@NonNull BySelector selector) {}
public static SearchCondition<UiObject2> findObject(@NonNull BySelector selector) {}
public static SearchCondition<List<UiObject2>> findObjects(@NonNull BySelector selector) {}
// 创建一个 Device 对象,然后先返回桌面
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
BySelector selector = By.text("foo");
UiObject2 foo = device.findObject(selector);
SearchCondition<UiObject2> searchCondition = Until.findObject(selector);
// 通过 UiDevice 进行等待
device.wait(searchCondition, 1000);
// 通过 UiObject2 进行等待
foo.wait(searchCondition, 1000);
不管是通过 UiDevice
进行等待还是通过 UiObject2
进行等待,最终走到的都是同一个 wait
方法:
public <U> U wait(Condition<? super T, U> condition, long timeout, long interval) {
long startTime = SystemClock.uptimeMillis();
U result = condition.apply(mObject);
for (long elapsedTime = 0; result == null || result.equals(false);
elapsedTime = SystemClock.uptimeMillis() - startTime) {
if (elapsedTime >= timeout) {
break;
}
SystemClock.sleep(interval);
result = condition.apply(mObject);
}
return result;
}
EventCondition
EventCondition
是 Android UI 自动化测试框架中用于表示事件条件的类。它的主要作用是在测试中判断某些特定事件是否发生,
通常用于等待某些事件完成,或者某些特定的 UI 元素状态发生变化。 EventCondition
需要重写 getResult
和 accept
两个接口方法。
EventCondition<Boolean> eventCondition = new EventCondition<Boolean>() {
@Override
public Boolean getResult() {
return null;
}
@Override
public boolean accept(AccessibilityEvent accessibilityEvent) {
return false;
}
};
Until
Until
是一个条件工厂类,定义了很多方法的返回值为 UiObject2Condition
、SearchCondition
和 EventCondition
的方法:
Public Method | 描述 |
---|---|
static @NonNull UiObject2Condition<Boolean> checkable(boolean isCheckable) |
返回一个条件,取决于 UiObject2 是否可选中。 |
static @NonNull UiObject2Condition<Boolean> checked(boolean isChecked) |
返回一个条件,取决于 UiObject2 是否已选中。 |
static @NonNull UiObject2Condition<Boolean> clickable(boolean isClickable) |
返回一个条件,取决于 UiObject2 是否可点击。 |
static @NonNull UiObject2Condition<Boolean> descContains(@NonNull String substring) |
返回一个条件,当对象的描述包含给定的字符串时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> descEndsWith(@NonNull String substring) |
返回一个条件,当对象的描述以给定的字符串结尾时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> descEquals(@NonNull String contentDescription) |
返回一个条件,当对象的描述与给定的字符串完全匹配时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> descMatches(@NonNull Pattern regex) |
返回一个条件,当对象的描述与给定的正则表达式匹配时。 |
static @NonNull UiObject2Condition<Boolean> descMatches(@NonNull String regex) |
返回一个条件,当对象的描述与给定的正则表达式匹配时。 |
static @NonNull UiObject2Condition<Boolean> descStartsWith(@NonNull String substring) |
返回一个条件,当对象的描述以给定的字符串开始时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> enabled(boolean isEnabled) |
返回一个条件,取决于 UiObject2 是否启用。 |
static @NonNull SearchCondition<UiObject2> findObject(@NonNull BySelector selector) |
返回一个搜索条件,当至少找到一个符合选择器的元素时满足该条件。 |
static @NonNull SearchCondition<List<UiObject2>> findObjects(@NonNull BySelector selector) |
返回一个搜索条件,当至少找到一个符合选择器的元素时满足该条件。 |
static @NonNull UiObject2Condition<Boolean> focusable(boolean isFocusable) |
返回一个条件,取决于 UiObject2 是否可聚焦。 |
static @NonNull UiObject2Condition<Boolean> focused(boolean isFocused) |
返回一个条件,取决于 UiObject2 是否获得焦点。 |
static @NonNull SearchCondition<Boolean> gone(@NonNull BySelector selector) |
返回一个搜索条件,当未找到任何符合选择器的元素时满足该条件。 |
static @NonNull SearchCondition<Boolean> hasObject(@NonNull BySelector selector) |
返回一个搜索条件,当至少找到一个符合选择器的元素时满足该条件。 |
static @NonNull UiObject2Condition<Boolean> longClickable(boolean isLongClickable) |
返回一个条件,取决于 UiObject2 是否可长按点击。 |
static @NonNull EventCondition<Boolean> newWindow() |
返回一个条件,取决于是否出现了新窗口。 |
static @NonNull EventCondition<Boolean> scrollFinished(@NonNull Direction direction) |
返回一个条件,取决于滚动操作是否在给定方向上完成。 |
static @NonNull UiObject2Condition<Boolean> scrollable(boolean isScrollable) |
返回一个条件,取决于 UiObject2 是否可滚动。 |
static @NonNull UiObject2Condition<Boolean> selected(boolean isSelected) |
返回一个条件,取决于 UiObject2 是否已被选中。 |
static @NonNull UiObject2Condition<Boolean> textContains(@NonNull String substring) |
返回一个条件,当对象的文本包含给定的字符串时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> textEndsWith(@NonNull String substring) |
返回一个条件,当对象的文本以给定的字符串结尾时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> textEquals(@NonNull String text) |
返回一个条件,当对象的文本与给定的字符串完全匹配时(区分大小写)。 |
static @NonNull UiObject2Condition<Boolean> textMatches(@NonNull Pattern regex) |
返回一个条件,当对象的文本与给定的正则表达式匹配时。 |
static @NonNull UiObject2Condition<Boolean> textMatches(@NonNull String regex) |
返回一个条件,当对象的文本与给定的正则表达式匹配时。 |
static @NonNull UiObject2Condition<Boolean> textNotEquals(@NonNull String text) |
返回一个条件,当对象的文本与给定的字符串不匹配时。 |
Configurator
Configurator
用于设置 UI Automator 测试的关键参数。设置后会立即生效,并且可以在测试运行期间随时更改。
修改参数前需要先通过调用 getInstance
获取一个实例。在使用修改后的参数运行测试后,务必恢复原始的参数值,否则这将影响其他测试用例。
Public Method | 描述 |
---|---|
long getActionAcknowledgmentTimeout() |
获取等待 UiObject 点击确认的当前超时时间。 |
static @NonNull Configurator getInstance() |
获取 Configurator 的单例实例。 |
long getKeyInjectionDelay() |
此方法已废弃。此参数不再使用(文本直接设置,而非通过按键)。 |
long getScrollAcknowledgmentTimeout() |
获取等待 UiScrollable 滚动操作确认的当前超时时间。 |
int getToolType() |
获取用于运动事件的当前工具类型。 |
int getUiAutomationFlags() |
获取用于获取 android.app.UiAutomation 实例的当前标志。 |
long getWaitForIdleTimeout() |
获取在开始 UiAutomator 操作之前等待用户界面进入空闲状态的当前超时时间。 |
long getWaitForSelectorTimeout() |
获取等待 UiObject 在用户界面中变为可见,以便能够通过 UiSelector 匹配的当前超时时间。 |
@NonNull Configurator setActionAcknowledgmentTimeout(long timeout) |
设置等待 UiObject 点击确认的超时时间。 |
@NonNull Configurator setKeyInjectionDelay(long delay) |
设置按键注入延迟(此方法已废弃)。 |
@NonNull Configurator setScrollAcknowledgmentTimeout(long timeout) |
设置等待 UiScrollable 滚动操作确认的超时时间。 |
@NonNull Configurator setToolType(int toolType) |
设置用于运动事件的工具类型。 |
@NonNull Configurator setUiAutomationFlags(int flags) |
设置获取 android.app.UiAutomation 实例时使用的标志。 |
@NonNull Configurator setWaitForIdleTimeout(long timeout) |
设置等待用户界面进入空闲状态的超时时间,在开始 UiAutomator 操作之前。 |
@NonNull Configurator setWaitForSelectorTimeout(long timeout) |
设置等待 UiObject 在用户界面中变为可见的超时时间,以便能够通过 UiSelector 匹配。 |
Viewer
UI Automator Viewer
在 Android 的 SDK 中提供了一个用于查找 UI 界面元素的工具:uiautomatorviewer.bat
。该工具的作用是可以通过连接的 Android
设备或模拟器截图当前应用的界面,方便开发者查看界面布局。
点击 uiautomatorviewer.bat
的 Device Screenshot
按钮,工具就会展示 UI 元素的层级树(Hierarchy),并显示每个元素的属性,如
text(文本)、resource-id(资源ID)、class(类名)、content-desc(内容描述)等。开发者可以通过该工具查看 UI 元素的各种属性,进而编写精确的
UI 自动化测试脚本。通过查看 UI 元素的定位信息(如 ID、类名、文本等),可以帮助定位元素进行点击、输入等操作。
Danger
uiautomatorviewer.bat
在 Java 1.8 的环境下运行良好。在其他的 Java 版本上(比如 11、17、18 等)会出现闪退的情况。
Weditor
除了使用 Android 原生提供的 uiautomatorviewer.bat
工具,其他的三方也提供了类似功能的工具。比如 Python 的自动化框架提供的
ATX Weditor 工具。
安装和使用 ATX Weditor 的步骤如下:
Step 1:安装 Python,推荐安装 Python 3。不知道如何安装的话,可以参考 安装 Python 这篇文章。
python --version
Step 2:安装 weditor 工具:
pip install weditor
Step 3:手机连接电脑,确保 adb 可以识别到设备,然后执行:
python -m weditor
执行成功后,打开浏览器访问:http://localhost:17310/
原文链接:https://blog.csdn.net/folcan/article/details/123441086
Warning
在安装过程中,若出现报错 UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 825:
illegal multibyte sequence
可以换一个版本安装:
pip install weditor==0.6.3
Warning
在启动 Weditor 后,点击浏览器报 AttributeError: 'Device' object has no attribute 'address'
时,可以修改 page.py
文件的 IP 地址:
\Lib\site-packages\weditor\web\handlers\page.py | |
---|---|
81 82 83 84 |
|