定位方式
id定位
resource-id代表id属性,使用方法:
self.driver.find_element(MobileBy.ID, "current_price")
# 不需要写全称,如这样 self.driver.find_element(MobileBy.ID, "com.xueqiu.android:id/current_price")
class定位
不推荐,因为几乎整个屏幕的控件都是一样的class。
看到下面的图片中,不同控件的class都是android.widget.TextView
Accessibility ID定位
找到元素的content-desc属性来定位。
driver.findElement(By.name("7")).click()
driver.findElementByAccessibilityId("divide").click()
driver.findElement(By.name("2")).click()
driver.findElementByAccessibilityId("equals").click() # Accessibility ID定位
xpath定位
appium中没css定位,使用xpath定位较多。使用xpath相对定位,不使用绝对定位
xpath定位基础知识:
-
通过元素本身的唯一属性定位
方法:找到目标元素所在的”精准元素“即唯一标识属性,使用此属性定位
通过id属性定位 -
通过上一级目录的唯一属性定位
方法:目标元素没有唯一属性,则去找到与目标元素相近的上级目录中”唯一元素“作为起始位置,然后根据此相对位置逐层往子目录编写到目标位置 -
xpath做布尔逻辑运算
例子:self.driver.find_element(MobileBy.XPATH, "//*[@text='热门' and @resource-id='com.xueqiu.android:id/title_text']")
注意:resource-id要写全称 -
目录元素存在层级关系
1.定位上一层再定位目标元素
例如:需要定位“热门”,先定位其上层再定位“热门”
先定位上层表达式://*[contains(@resource-id,'title_container')]
2.根据共同的父元素定位
如上,需要获取到阿里巴巴香港上市的股价,先根据09988定位到共同的父元素,在定位价格275.6
以上是通过层层定位,找到共同的上层://*[contains(@resource-id,'stockCode') and @text='09988'] /../../..
下面通过resource-id找到价格
表达式如下:
//*[contains(@resource-id,'stockCode') and @text='09988'] /../../..//*[contains(@resource-id,'current_price')]
-
模糊定位
contains 方法(包含)
定位表达式://*[@text='热门' and contains(@resource-id,'title_text') ]
关于xpath定位的总结:首先有单一属性能够定位元素,优先使用单一元素定位;其次,如果单一元素无法定位,尝试使用逻辑运算组合定位;最后,考虑使用层级定位。多使用contains模糊定位可以缩短表达式。
参考文章:https://blog.csdn.net/hou_angela/article/details/80305828
使用AndroidAutomator定位
description就是content-desc属性。
driver.findElementByAndroidUIAutomator("new UiSelector().text("9")").click()
driver.findElementByAndroidUIAutomator("new UiSelector().description("plus")").click()
driver.findElementByAndroidUIAutomator("new UiSelector().resourceId("com.android.calculator2:id/digit6")").click()
driver.findElementByAndroidUIAutomator("new UiSelector().description("equals")").click()
AndroidAutomator定位只适用于android,其没有空间关系,通过众多条件精准定位到元素,定位速度快,但是表达式可能会很复杂,很少使用。
比较实用的一点是滑动到指定文本,如下:
def test_toast(self):
self.driver.find_element(By.XPATH,"//*[@text='Views']").click()
# 滚动查找,直到查找到Popup Menu点击
scroll_to_element = (
MobileBy.ANDROID_UIAUTOMATOR,
'new UiScrollable('
'new UiSelector().scrollable(true).instance(0))'
'.scrollIntoView('
'new UiSelector().text("Popup Menu").instance(0));')
self.driver.find_element(*scroll_to_element).click()
# 页面上看到文本是“AKE A POPUP!”,直接使用此文本查找报错,通过uiautomatorviewer可以看到是"Make a Popup!"
# self.driver.find_element(By.XPATH, "//*[@text='MAKE A POPUP!']").click()
self.driver.find_element(MobileBy.ACCESSIBILITY_ID, "Make a Popup!").click() # ACCESSIBILITY_ID是定位resource-id
self.driver.find_element(By.XPATH, "//*[@text='Search']").click()
# toast定位
toast=self.driver.find_element(By.XPATH, "//*[@class='android.widget.Toast']").text
assert "Search" in toast
assert "Clicked" in toast
定位工具
Appium desktop定位
每次定位都需要先执行脚本,到达定位控件的上下文。desktop定位的好处是可以马上验证表达式是否正确
可参考:https://www.cnblogs.com/Uni-Hoang/p/13734384.html
-
进行配置
-
刷新页面
-
选择定位方式
-
查找元素
-
验证
uiautomatorviewer
uiautomatorviewer是android SDK自带的工具,只适用与android定位。通过截屏并分析XML布局文件的方式,为用户提供控件信息查看服务。该工具位于SDK目录下的toolsin子目录下。可以看到,它是通过bat文件启动的。
-
首先要安装SDK,可以在Android Studio下安装SDK,也可以单独安装SDK
安装后所在目录
-
将所在目录配置到PATH环境变量中:E:softwareAndroidSDK oolsin
直接启动
配置path环境变量后
-
界面介绍
整个界面分四个区域:
(1)工作栏区(上)
共有4个按钮。从左至右分别用于:打开已保存的布局,获取详细布局,获取简洁布局,保存布局。点击保存,将存储两个文件,一个是图片文件,一个是.uix文件(XML布局结构)
第二按钮(Device Screenshoot uiautomator dump)与第三按钮(Device Screenshoot with Compressed Hierarchy uiautomator dump –compressed)的区别在于,第二按钮把全部布局呈现出来,而第三按钮只呈现有用的控件布局。比如某一 Frame存在,但只有装饰功能,那么点击第三按钮时,可能不被呈现。
(2)截图区(左),显示当前屏幕显示的布局图片
(3)布局区(右上),已XML树的形式,显示控件布局
(4)控件属性区(右下),当点击某一控件时,将显示控件属性 -
进行定位
图中使用ID定位
def test_getPrice(self):
self.driver.find_element(MobileBy.ID,"tv_search").click() # MobileBy继承By
self.driver.find_element(MobileBy.ID,"search_input_text").send_keys("阿里巴巴")
self.driver.find_element(MobileBy.ID,"name").click() # 第一张图片定位
# 获取价格,转换为float类型进行断言
assert float(self.driver.find_element(MobileBy.ID, "current_price").text) > 250 # 第二张图片定位
uiautomatorviewer定位遇到的问题
-
Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't exist!
原来好好的,但是不知道怎么就出现这个。
在网上找了很多解决办法,可以试试:
1、在cmd命令窗口中输入 adb root 即可
2、重启手机无效
3、重新把手机拔了再插
4、重启appuim
5、重启uiautomatorviewer.bat(尝试了没用)
6、打开手机开发者权限,将USB调试按钮重新启动就好了
7、重启模拟器(我使用木木模拟器,重启后可以重新识别)
大家可以试试看看哪种方式适合自己。 -
无法连接adb
参考:https://www.jianshu.com/p/2105174c68b3 -
弹窗处理
-
运行报错
uiautomatorviewer跟appium server不能同时使用,这时需要先停止appium server