APP自动化基础之元素定位

mobileby

在开始讲元素定位的方式时,我们先来看下appium中元素定位的相关模块:mobileby.py:
在这里可以看到,MobileBy这个类继承了selenium中的元素定位的类:By,然后根据手机特性又另外自己写了一堆元素定位的方式。所以理论上,对于android app的元素定位来说,既能使用selenium中的八大元素定位方式,也能使用android所特有的4个定位方式。

from selenium.webdriver.common.by import By


class MobileBy(By):
    IOS_PREDICATE = '-ios predicate string'
    IOS_UIAUTOMATION = '-ios uiautomation'
    IOS_CLASS_CHAIN = '-ios class chain'
    ANDROID_UIAUTOMATOR = '-android uiautomator'
    ANDROID_VIEWTAG = '-android viewtag'
    ANDROID_DATA_MATCHER = '-android datamatcher'
    ANDROID_VIEW_MATCHER = '-android viewmatcher'
    WINDOWS_UI_AUTOMATION = '-windows uiautomation'
    ACCESSIBILITY_ID = 'accessibility id'
    IMAGE = '-image'
    CUSTOM = '-custom'

从appium inspector看元素定位方式

虽然理论上来说,app的定位方式看起来可选择的更多了,但由于app的特性,web的很多定位方式在app中就不适用了。比如:link_text、partial_link_text、name、tagname、classname、css_selector都不再适用,因为这些都只适用于html中,而app是xml进行元素标识的,所以这些就用不了了。
接下来我们看下appium inspector的元素属性区域所展示的这些属性哪些可以被用来定位。

  • id。id确实可以作为app中的一种定位方式,但并不同于web中当前页面元素的id是唯一的这个特性,在app中id其实是会变化的,同一个id值可能会找到多个元素。所以到了app这边,通过id的定位方式就没那么稳定了;
  • xpath。很高兴又能看到xpath!但其实在appium中,官方是不建议用xpath进行定位的,它是一种脆弱的定位方式,因为它使用的是绝对路径:
    在这里插入图片描述

但如果你写成相对路径的话,也是可以用来定位的;
在这里插入图片描述

  • elementId。或许看到有个id你又会高兴了。这总该是唯一的了吧!很遗憾,它也是会变化的,所以也不适合用来定位:
    在这里插入图片描述
    在这里插入图片描述
  • index。这是子标签的索引,用来标识子标签是父标签下的第几个标签。这个可以用来辅助定位,比如根据层级关系来找父级或子级:
    在这里插入图片描述
  • text。文本内容,这个也只能用来辅助定位
  • class。注意这里的class并不是web中的classname,因为在app中是没有css的(webapp除外)。这里的class其实相当于web中的tagname,在app中标签名相同的太多了,所以也不适合用来定位
  • package。当前app中所有元素的package都是一样的
  • content-desc。这个属性比较特别,性必须在辅助浏览工具(比如TalkBack)开启后才能使用,android系统会自动使用人声朗读控件上android:contentDescription属性说指向的内容。这样用户就可以知道这个控件是做什么用的。这个属性主要是让一些视力有障碍的用户明白这个控件是干嘛用的。可能你会说,这肯定不会用来做元素定位,一来是它的用途比较特别,而来是很多元素它的content-desc就是空的。但其实content-desc就是app中一种常用的元素定位方式(后面会讲到)
  • 布尔值属性。后面有一些只有true或false两个值的属性,它们也不太适合用来定位元素,因为很不稳定:
    在这里插入图片描述
  • bounds。元素所在坐标位置。虽然说坐标的值是唯一的,看起来很适合用来作为元素定位方式,但如果你想用这种方式来定位元素的话会相当地麻烦,需要调用TouchAction类下的多个方法。所以这里不推荐用这种方式进行定位
  • resource-id。这是android为每个资源单独分配的id,跟上面id的值是相等的。

app常见定位方式

如何选择元素定位方式?

app元素定位实战

id

上面说过,元素定位第一优先选择的是id,但前提是必须保证id的唯一性。
这里我们定位开始按钮:
在这里插入图片描述
通过search for element查看id的唯一性:
在这里插入图片描述
可以看到id是唯一的:
在这里插入图片描述
把id方式的元素定位写进代码中如下:

from appium import webdriver

caps = {
  "platformName": "Android",
  "deviceName": "emulator-5554",
  "automationName": "UiAutomator1",
  "appPackage": "cc.forestapp",
  "appActivity": "cc.forestapp.applications.SplashActivity",
  "noReset": True
}
driver = webdriver.Remote(
    command_executor="http://127.0.0.1:4723/wd/hub",
    desired_capabilities=caps
)

#定位元素,操作元素
element = driver.find_element(MobileBy.ID,"cc.forestapp:id/button_text")
element.click()

xpath

xpath在app中要写成相对路径的方式。
这里我们仍然定位的是开始按钮,找到它的标签名为:androidx.drawerlayout.widget.DrawerLayout,然后看到它有一个resource-id,我们可以用这个作为辅助的定位方式,即找到一个元素标签,它具有resource-id的属性://androidx.drawerlayout.widget.DrawerLayout[@resource-id=“cc.forestapp:id/drawer_layout”]
在这里插入图片描述
通过search for element校验元素表达式的正确性:
在这里插入图片描述
可找到一个元素:
在这里插入图片描述
写入代码中如下:

from appium import webdriver

caps = {
  "platformName": "Android",
  "deviceName": "emulator-5554",
  "automationName": "UiAutomator1",
  "appPackage": "cc.forestapp",
  "appActivity": "cc.forestapp.applications.SplashActivity",
  "noReset": True
}
driver = webdriver.Remote(
    command_executor="http://127.0.0.1:4723/wd/hub",
    desired_capabilities=caps
)

#定位元素,操作元素
element = driver.find_element("xpath",'//androidx.drawerlayout.widget.DrawerLayout[@resource-id="cc.forestapp:id/drawer_layout"] ')
element.click()

content-desc

这个元素定位方式真的比较靠运气,因为很多情况下,元素的这个属性都是空的,但如果某个元素的这个属性不是空的,那也是个不错的定位方式。
这里我们假设开始按钮的content-desc的值就为开始,那么怎么通过代码编写呢?
在这里插入图片描述
这里介绍两种方法:

"""省略前面代码"""
#方法一:find_element
from appium.webdriver.common.mobileby import MobileBy
element = driver.find_element(MobileBy.ACCESSIBILITY_ID,'开始')
element.click()

#方法二:find_element_by_accessibility_id
element2 = driver.find_element_by_accessibility_id('开始')

uiautomator

这是除了id之外最为常用的定位方式了。如果通过id、content-desc都不好定位(如id不唯一或content-desc值为空),那不要用xpath,直接选用uiautomator,因为它的执行速度比xpath快。

直接定位

在这里插入图片描述
uiautomator定位方式需要单独用字符串封装一段java代码。在java代码中,我们先要new一个uiautomator对象,然后通过对象调用方法。
在uiautomator中,每一个属性在java中都是一个方法,而方法的值就是属性的值。比如说这里resourceId,在java中就可以这么写:resourceId(“cc.forestapp:id/button_text”)。所以这里开始按钮用uiautomator表达式就可以这样写:
‘new UiSelector().resourceId(“cc.forestapp:id/button_text”)’
代码如下:

"""省略前面代码"""
from appium.webdriver.common.mobileby import MobileBy
selector = 'new UiSelector().resourceId("cc.forestapp:id/button_text")'
element = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,selector).click()

这里需要注意一点:在java中,字符串必须要用双引号,不能用单引号。所以python中用字符串封装java代码时外面最好用单引号,或者如果非要用双引号的话,可以在java代码中字符串部分的双引号前面加上\进行转义,表示这就是纯粹的单引号,并不代表字符串,就像这样:

selector = "new UiSelector().resourceId(\"cc.forestapp:id/button_text\")"

父级找子级

uiautomator也可以像xpath一样,根据父级元素找子级元素。
这里依然拿开始按钮做定位。可以看到开始按钮元素还有一个父级元素:
在这里插入图片描述
我们先定位到父级元素,比如说通过class属性和enabled属性进行定位:
className(“android.view.View”).enabled(true)
在这里插入图片描述
接着找它下面的子元素,这里我们可以通过resource-id属性来定位:resourceId(“cc.forestapp:id/button_text”)
在这里插入图片描述
合起来就变成这样:
new UiSelector().className(“android.view.View”).enabled(true).childSelector(new UiSelector().resourceId(“cc.forestapp:id/button_text”))
我们通过search for element来根据uiautomator方式查找元素,是可以找得到的:
在这里插入图片描述
在这里插入图片描述
写入代码中如下:

"""省略前面代码"""
from appium.webdriver.common.mobileby import MobileBy
selector = 'new UiSelector().className("android.view.View").enabled(true).childSelector(new UiSelector().resourceId("cc.forestapp:id/button_text"))'
element = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,selector).click()

元素等待

跟web一样,元素的定位在很多情况下也需要等待。web自动化测试中的三大等待依然使用与app自动化测试,这里不再展开赘述。

常用元素定位辅助工具

除了appium自带的inspector之外,还有两款不错的元素定位的辅助工具:

  • android sdk自带的uiautomator
  • 网易出的weditor
    好处:1.xpath使用的是相对定位
    2.可方便查看package和activity
    3.可显示一个元素的坐标
    4.可自动生成python的自动化测试代码

appium中无法启动uiautomator2

原因

uiautomator2可能和其他的第三方定位工具(如weditor)同时存在,导致产生两个adb从而造成冲突

解决方法

  • 关闭第三方定位工具,重启appium server
  • 还不行,则删除真机或模拟器上的appium settings,再次启动appium server
  • 还不行,则重启模拟器或真机,再次启动appium server
  • 还不行,可停掉uiautomator2的服务
    步骤:1.通过以下命令查找uiautomator服务:
    adb shell pm list package | grep uiautomator
    也可以查看instrumentaion:
    adb shell pm list instrumentaion
    2.卸载uiautomator2服务
    adb uninstall io.appium.uiautomator2.server
    adb uninstall io.appium.uiautomator2.server.test
    3.重启appium server
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页