第一种 APP定位
1.通过ID定位元素,对应【resource-id】属性
代码示例:
driver.find_element_by_id("com.tencent.wework:id/e0y")
2.通过Name定位元素,对应【text】属性
还是定位通讯录,示例代码如下:
driver.find_element_by_name("通讯录")
运行后会出现
selenium.common.exceptions.InvalidSelectorException: Message: Locator Strategy 'name' is not supported for this session
坊间传闻appium自1.5版本开始就已经抛弃了name这种定位方法,so,推荐使用xpath来定位
driver.find_element_by_xpath('//*[@text="通讯录"]')
3.通过accessibility_id定位元素,对应【content-desc】属性
driver.find_element_by_accessibility_id()
4.通过ClassName定位元素,对应【class】属性
driver.find_element_by_class_name()
不推荐使用,因为页面很容易出现多个元素class相同的情况
第二种 xpath 定位
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历
1. 如果元素的 text 唯一
driver.find_element_by_xpath("//*[@text='通讯录']")
2. 如果元素的 id 唯一
driver.find_element_by_xpath("//*[@resource-id='com.tencent.wework:id/b09']")
3. 如果元素id不唯一,text唯一
如企业微信APP 的底部按钮
可以看到id 有多个,但是text 唯一,这个时候需要id + text 组合定位,比如定位通讯录示例代码如下
driver.find_element_by_xpath("//*[@resource-id='com.tencent.wework:id/e0y'][@text='通讯录']")
4.如果元素class 唯一
driver.find_element_by_xpath("//android.widget.EditText")
driver.find_element_by_xpath("//*[@class='android.widget.EditText']")
根据xpath语法,以上两种都可行
5. 通过content-desc 属性定位
driver.find_element_by_xpath("//*[contains(@text,'通讯录')]") #精确匹配
driver.find_element_by_xpath("//*[contains(@content-desc,'通')]") #模糊匹配
6.以上的属性都不唯一时,解决方案
a.组合定位大法
通过xpath谓语 多条件 组合
附学习链接 https://www.w3school.com.cn/xpath/xpath_syntax.asp
driver.find_element_by_xpath("//*[@resource-id='com.tencent.wework:id/e0y'][@text='通讯录']")
driver.find_element_by_xpath('//*[contains(@resource-id, "com.tencent.wework:id/e0y") and @text="通讯录"]')
b.父子关系定位
当一个元素父级唯一,子级不唯一,可以用此法, 如企业微信APP底部按钮的通讯录
driver.find_element_by_xpath('//*[@resource-id="com.tencent.wework:id/gwt"]//*[@text="通讯录"]')
如果一个元素它的子级时唯一的,父级不唯一,相反,可以用子定父
c.兄弟关系定位
通过子元素,先找到父元素,,在找父元素,再找父元素下的子元素,同样可以进行兄弟元素定位,
用到xpath 轴的知识
https://www.w3school.com.cn/xpath/xpath_axes.asp
以企业微信app 的通讯录为例,经通过观察 xpath 可以由【消息】定位到【通讯录】
driver.find_element_by_xpath('//*[@text="消息"]/../../following-sibling::android.widget.RelativeLayout//*//*[@text="通讯录"]')
实际需要灵活运用
c.爷孙关系定位
如果一个元素的父级不唯一,但是父级的父级是唯一的,可以用这个来定位
self.driver.find_element_by_xpath('//*[@resource-id="com.tencent.wework:id/gwt"]/android.widget.RelativeLayout/android.widget.RelativeLayout//*[@text="通讯录"]')
一个元素往上找父级,找到唯一的一个父级后,在往下进行定位,根据实际情况来灵活使用
第三种 uiautomator定位元素
Android的原生测试框架的定位方式,定位速度快。
使用uiautomatorviewer,可以分析待测试应用UI控件的id,text等等各种属性,和布局上的层次关系。
windows下运行tools下的 uiautomatorviewer.bat
liunx下运行./uiautomatorviewer 启动该工具
基本语法:
driver.find_element_by_android_uiautomator(xx)
1.通过id定位,对应【resource-id】属性
new UiSelector().resourceId("xxx") #精确匹配
new UiSelector().resourceIdMatches("regex") #模糊匹配
2.通过name定位,对应【text】属性
常用text方法
new UiSelector().text("通讯录") #精确匹配
new UiSelector().textContains("通讯") #模糊匹配
new UiSelector().textStartsWith("通") # 以text什么开始
new UiSelector().textMatches("^通.*") # 正则匹配text
3.通过ClassName定位元素,对应【class】属性
new UiSelector().className("android.widget.TextView") # 精确匹配
new UiSelector().classNameMatches("^android.widget.*") # 模糊匹配
4.通过description,对应【contenet-des】属性
new UiSelector().description("contenet-des属性") #精确匹配
new UiSelector().descriptionContains("string") #模糊匹配
new UiSelector().descriptionStartsWith("通") #以什么开头
new UiSelector().descriptionMatches(".*讯$") #正则匹配
5.父子定位 childSelector
resourceId("xx").childSelector(text("xx"))
6.兄弟定位 fromParent
resourceId("xx").fromParent(text("xx"))
7.滑动 查询 元素
适用于滑屏寻找元素
new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("查找的元素文本").instance(0))
8.组合定位
resourceId("com.tencent.wework:id/gwt").text("通讯录")
灵活根据resourceId、text、class自由组合定位
以上只总结了android的定位方法,ios其实也差不多
appium官方查询文档:Find Elements - Appium