Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍

 

Appium实现自动化底层是依赖UiAutomator框架,定位元素也是经由UiAutomator处理后转换Accessibility服务对象完成元素查找并且操作。在前面介绍过Appium-Desktop支持的ID、XPATH、ACCESSIBILITY_ID、CLASS_Name定位,对于这四种定位比较容易理解,剩下的ANDROID_UIAUTOMATOR定位在这篇文章介绍。

一、疑问

对于ANDROID_UIAUTOMATOR的使用出于自己的2个疑问

1.为什么Appium-Desktop不支持非常实用的NAME定位?

2.ANDROID_UIAUTOMATOR这种定位方式的价值有多大?

二、ANDROID_UIAUTOMATOR定位使用

对于Appium来说支持ANDROID_UIAUTOMATOR花费的代码量比ID、ACCESSIBILITY_ID、CLASS_Name加起来都多N倍,对于支持ID、ACCESSIBILITY_ID、CLASS_Name非常简单,直接把入参的String内容传入到UiAutomator对应的方法就搞定,但是对于ANDROID_UIAUTOMATOR就需要一大堆的代码处理,看下面代码:

if (by instanceof ById) {
    String locator = rewriteIdLocator((ById) by);
    return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.res(locator));
} else if (by instanceof By.ByAccessibilityId) {
    return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.desc(by.getElementLocator()));
} else if (by instanceof ByClass) {
    return CustomUiDevice.getInstance().findObject(androidx.test.uiautomator.By.clazz(by.getElementLocator()));
} else if (by instanceof By.ByXPath) {
    final NodeInfoList matchedNodes = getXPathNodeMatch(by.getElementLocator(), null, false);
    if (matchedNodes.isEmpty()) {
        throw new ElementNotFoundException();
    }
    return CustomUiDevice.getInstance().findObject(matchedNodes);
} else if (by instanceof By.ByAndroidUiAutomator) {
    UiSelector selector = toSelector(by.getElementLocator());
    if (selector == null) {
        throw new UiSelectorSyntaxException(by.getElementLocator(), "");
    }
    return CustomUiDevice.getInstance().findObject(selector);
}

从源码来看ID、ACCESSIBILITY_ID、CLASS_Name这些都是UiAutomator支持的定位方式,唯有XPATH、ANDROID_UIAUTOMATOR是需要经常特殊处理的;ANDROID_UIAUTOMATOR的定位经过ElementLocationHelpers、UiAutomatorParser、UiScrollableParser、UiSelectorParser、UiExpressionParser这5个类的一系列方法逐渐分解,最终返回用户想要定位的元素对象(XPATH的源码分析就不在这篇文章叙述),举例说明:

driver.findElementByAndroidUIAutomator("new UiSelector().resourceId(\"android:id/content\").childSelector(new UiSelector().resourceId(\"ymxh.main:id/user_name\"))");

Appium Server需要把入参的String分解,先拿到new UiSelector()通过反射得到该UiSelector对象,再通过反射去调用它的resourceId方法、childSelector方法;有兴趣可以自己去研究一下Appium Server的源码。

1.Text定位

Appium-Desktop已经不支持Name的定位方式,但是使用ANDROID_UIAUTOMATOR依然可以间接的通过text属性来定位元素,这或许就是为什么Appium-Desktop可以放弃Name定位方法的考虑,从上面举例也可以看出ANDROID_UIAUTOMATOR其实可以完全替代ID、ACCESSIBILITY_ID、CLASS_Name方法。

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第1张图片

new UiSelector().text("text文本")

new UiSelector().textContains("包含text文本")

new UiSelector().textStartsWith("以text文本开头")

new UiSelector().textMatches("正则表达式")

2.resourceId

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第2张图片

new UiSelector().resourceId("id")

3.className

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第3张图片

new UiSelector().className("className")

4.description

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第4张图片

new UiSelector().description("contenet-des属性")

5.childSelector

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第5张图片

父元素下找子元素

new UiSelector().resourceId("ymxh.main.id/spinner_job").childSelector(new UiSelector().resourceId("android:id/text1"))

6.cfromParent

Appium基础学习之 | ANDROID_UIAUTOMATOR定位介绍_第6张图片

同层元素

new UiSelector().resourceId("ymxh.main.id/webui_auto").childSelector(new UiSelector().resourceId("ymxh.main.id/interf_auto"))

当然使用ANDROID_UIAUTOMATOR定位方式可以非常灵活方便,只要是符合UiAutomator风格的定位都可以使用,想了解更多方法可以参考一下UiAutomator源码中UiSelector类支持的方法,选择使用。文中只介绍了常见的一些方法,请谅解。

你可能感兴趣的:(Appium,Appium学习)