Appium 讨论一下 Appium android_uiautomator 定位方式吧

醋精测试媛 · 2021年03月15日 · 最后由 醋精测试媛 回复于 2021年03月16日 · 5087 次阅读

曾使用 Xpath 定位,感觉定位速度好慢。看到有人说 UiAutomator 的定位方式比 Xpath 快,就想试试。
搜索了很多 UiAutomator 定位方法的介绍,大多都是很简单的,如何用 resourceId, text, className,description 等来定位的介绍,还有就是组合定位的方法:通过父元素定位子元素 UiSelector.childSelector 和通过同一级父元素下的兄弟元素的定位方法 UiSelector.fromParent,但是觉得其中有许多值得进一步确认的地方,以及想要请教一下大家使用这种定位方式的细节。

  • 一个是 childSelector 的定位,当我通过父元素定位子元素,明明存在很多个子元素,但是只能定位到第一个:

    如下图

    定位方式resourceId("com.starnet.GreenHome:id/recycle_my_fun").childSelector(className("android.view.ViewGroup"))
    结果

    经过测试发现,可以通过resourceId("com.starnet.GreenHome:id/recycle_my_fun").childSelector(className("android.view.ViewGroup").index(1))定位到第二个,那怎么定位到所有元素呢?
    看到有人问过这个问题,但是没有回答( https://testerhome.com/topics/15570
    注:经过多次试验,当使用 python 语言时,resourceId 必须用双引号括起来,不然定位不到。

  • 一个则是 https://testerhome.com/topics/27597 中提到的 UiScrolllable,滚动查找时,当找不到则会先选中中间那个,所以会打开中间那个的页面,有没有办法不点击呢?

    代码如下:
    new UiScrollable(new UiSelector().resourceId("com.starnet.GreenHome:id/recycle_community_service")).scrollIntoView(new UiSelector().text("信息"))
    结果:使用 appium server 进行搜索时,没有滑动,而是点开了中间那个方块。运行代码,提示目标元素不存在。
    详见: https://testerhome.com/topics/27597

最佳回复
哲豪 回复
  • 定位代码应该没有问题: common_element_loc = ( MobileBy.ANDROID_UIAUTOMATOR, 'UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).findObject(By.res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()')

显示错误为:

selenium.common.exceptions.InvalidSelectorException: Message: Could not parse expression `new  UiSelector().UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).findObject(By.res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()`: UiSelector has no `UiDevice.getInstance` method

应该是因为默认是 appium 以 new UiSelector() 的使用的方法的原因。暂时想到的是只能使用 xpath 方法。

共收到 20 条回复 时间 点赞

你是要获取某个父节点 下的 所有子节点吗?
滑动查找 可以自己写,不用封装好的。scrollIntoView 实现的是 尽量把控件滑动中间,所以可能会触发到中间控件的点击

哲豪 回复

1.是的,请问有办法吗
2.自己写指的是使用 appium 的 swipe 吗,我之前试过,觉得耗时比较长。

uiautomator 是 获取到父节点 后调用 getChildren,就可以拿到 下面 可见的 所有子节点了

appium 可以 试试 xpath+ "//node()[contains(@xxx,'xxx')]" , 这样应该可以获取 获取到指定父节点下的 子节点

哲豪 回复

看了官方文档后, 我试过

  • new UiDevice().findObject(new BySelector().res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()
  • new UiObject().findObject(new BySelector().res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren() 但是提示找不到元素,想问 getChildren 是哪个下面的呢?还是说 getChildren() 里面需要输入参数?

单独通过 id 查,能找到元素吗

哲豪 回复

直接 resourceId("com.starnet.GreenHome:id/recycle_my_fun") 或者 className("android.view.ViewGroup") 可以查到,但是想查找的是某个元素下的多个子元素,如果直接查找子元素,会导致子元素查找的不对,因为还有别的和子元素的 id/class 相同的元素。

由于 XPATH 查找耗时比较长,所以考虑了 automator,就是 appium 中也可以用 android_automator 定位方式进行定位。

new UiDevice().findObject(new BySelector().res("com.starnet.GreenHome:id/recycle_my_fun")) 😧 这样子 能查到?

哲豪 回复

都不能查找到。

resourceId("com.starnet.GreenHome:id/recycle_my_fun") 指的是 new UiSelector(). resourceId("com.starnet.GreenHome:id/recycle_my_fun")

你用的是 UiObject 吧 , 不是 UiObject2 。 😧


UiObject2 可以 获取 所有子节点

哲豪 回复

我是仿照 https://blog.csdn.net/swordgirl2011/article/details/50993157?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&dist_request_id=1328641.52178.16157973103334907&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control 上 3.2 的案例做的。

后来也查了文档

UiDevice 返回的是 UiObject2 ,然后就可以使用 getChildren 了,但是试过了:
new UiDevice().findObject(new BySelector().res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()
是没有获取到的。

这种写法 不会报错吗?

哲豪 回复

因为使用 python ,所以不知道有没有报错,是看的android.support.test.uiautomator.BySelector - [android.support.test.uiautomator.BySelector](https://www.apiref.com/android-zh/android/support/test/uiautomator/BySelector.html)上面的。确实这个函数的参数是 BySelector 的类型

哲豪 回复

当然,我两个都试过了,都不行。


😂 试过了 正常获取

哲豪 回复
  • 定位代码应该没有问题: common_element_loc = ( MobileBy.ANDROID_UIAUTOMATOR, 'UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).findObject(By.res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()')

显示错误为:

selenium.common.exceptions.InvalidSelectorException: Message: Could not parse expression `new  UiSelector().UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).findObject(By.res("com.starnet.GreenHome:id/recycle_my_fun")).getChildren()`: UiSelector has no `UiDevice.getInstance` method

应该是因为默认是 appium 以 new UiSelector() 的使用的方法的原因。暂时想到的是只能使用 xpath 方法。

automationName 你写的啥

哲豪 回复

automationName 是指定位方式 MobileBy.ANDROID_UIAUTOMATOR 吗? 这个值是 “-android uiautomator”

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册