恢弘志士之气,不宜妄自菲薄。这篇文章主要讲述Android定位元素与操作相关的知识,希望能为你提供帮助。
一、常用识别元素的工具
uiautomator:android SDK自带的一个工具,在tools目录下
monitor:Android SDK自带的一个工具,在tools目录下
Appium-desktop:appium-desktop 自带的工具,启动appium-desktop后,点击右上角的 放大镜 图标,进行一些常规配置即可使用。
参考:http://www.cnblogs.com/kaerxifa/p/7808073.html
使用Appium Inspector定位的元素
文章图片
二、元素定位 1.格式:find_element_by_定位方式(value) 通过id定位 (取resource-id的值): driver.find_element_by_id("com.wuba.zhuanzhuan:id/azo") 也可以直接用id后面的内容driver.find_element_by_id("azo") 通过 android_uiautomator定位 resourceId 方式
driver.find_element_by_android_uiautomator(\'new UiSelector().resourceId("%s")\')
text 方式
driver.find_element_by_android_uiautomator(\'new UiSelector().text("%s")\')
description 方式
driver.find_element_by_android_uiautomator(\'new UiSelector().description("%s")\')
className 方式
driver.find_element_by_android_uiautomator(\'new UiSelector().className("%s")\')
index 方式
driver.find_element_by_android_uiautomator(\'new UiSelector().index("%s")\')
className + index 方式
driver.find_element_by_android_uiautomator(
\'new UiSelector().className("%s").childSelector(new UiSelector().index("%d"))\')
【Android定位元素与操作】伪xpath方法定位
driver.find_element_by_android_uiautomator(‘new UiSelector().text("Custom View").fromParent(new UiSelector().text("Accessibility Service"))‘).click()#通过同级元素定位同级元素
driver.find_element_by_android_uiautomator(‘new UiSelector().className("android.widget.ListView").childSelector(new UiSelector().text("Custom View"))‘).click()#通过父级元素定位子集元素
通过class_name定位 (取class的内容) driver.find_element_by_class_name("android.widget.RelativeLayout") 通过xpath定位 (取xpath得内容) driver.find_element_by_xpath("//android.widget.LinearLayout[1]/android.widget.XXX") 通过text定位 (需要使用uiautomator的定位方式,使用text的内容) driver.find_elements_by_android_uiautomator("new UiSelector().text(\\"+关注\\")") 使用这里需要注意一下,通过text定位的结果是个list,不能直接click。所以如果要点击需要取数组的值,比如下面是点击找到的第一个元素driver.find_elements_by_android_uiautomator("new UiSelector().text(\\"+关注\\")")[0].click() 通过css_selector定位(webview) 只适用于webview的html页面,继承自webdriver,与pc版本的UI测试一致 driver.find_element_by_css_selector() 通过link_text定位(webview) 只适用于webview容器中的html页面,继承自webdriver,与pc版本的UI测试一致 driver.find_element_by_link_text() 通过name定位 web view容器中的html页面可以用name定位,native并没有name属性 driver.find_element_by_name() 2.定位元素的另一种写法:find_element(by,value) find_element_by_方式(value)实际调用的都是find_element(by,value) 需要导入这个包:from selenium.webdriver.common.by import By 例如:定位id为ag2的元素 方式一:driver.find_element_by_id("ag2”) 方式二:driver.find_element(By.ID,"ag2") 这个操作的好处是可以直接把操作的by和value放到一个元组里,然后调用通用方法来传参获得元素结果cateid=(By.ID,"ag2") driver.find_element(*cateid).click() by的操作可以是: By.ID 相当于by_id By.CLASS_NAME 相当于by_class_name By.XPATH 相当于by_xpath By.NAME 相当于by_nameBy.TAG_NAME 相当于by_tag_nameBy.CSS_SELECTOR 相当于by_css_selector By.LINK_TEXT 相当于by_link_text 3.find_elements_by_定位方式(value)返回元素数组 用法与find_element_by_方式(value)一致,但是返回一个数组。可以通过数组的索引来访问具体的某个结果 例如:通过class_name定位到多个元素,我想点击第一个元素 driver.find_elements_by_class_name("android.widget.RelativeLayout”)[0].click() 4.返回元素数组的另一种写法:find_elements(by,value) 用法与find_element(by,value)一致,但是返回一个数组。可以通过数组的索引来访问具体的某个结果 例如:通过class_name定位到多个元素,我想点击第一个元素 driver.find_elements(By.CLASS_NAME,"android.widget.RelativeLayout”)[0].click() 5.通过元素定位元素 可以先找到某个元素,然后再进一步定位元素 find_element_by_class_xpath(“xxx”).find_element_by_name(“yyy") 三、元素操作 找到元素后可以对元素进行的操作,例如上面讲的进一步定位元素 1.click() //点击操作 也可以用tab实现点击操作 driver.find_element_by_id("com.wuba.zhuanzhuan:id/ae8").click() 2.clear() //清空输入框内容 driver.find_element_by_id("com.wuba.zhuanzhuan:id/ij").clear() 3.send(xx) //输入框内输入内容 driver.find_element_by_id("com.wuba.zhuanzhuan:id/ij").send_keys("test content") 4.text //获得元素的text内容 print(driver.find_element_by_xpath(" //android.widget.LinearLayout[1]//xxx").text) 四、触摸操作 1.driver.tap([坐标],持续点击时间) 除了定位到元素的点击外,也可以通过tab实现坐标的点击 driver.tap(driver.tap([(216,1776)],2)) 2.TouchAction(driver) TouchAction对象包含(tab)、press(短按)、move_to(滑动到某个坐标)等方法 通过TouchAction对象,添加tap、move_to等操作,然后perform()执行,可以实现解锁屏幕等功能 规范中的可用事件有: * 短按 (press)
* 释放 (release)
* 移动到 (moveTo)
* 点击 (tap)
* 等待 (wait)
* 长按 (longPress)
* 取消 (cancel) * 执行 (perform)
文章图片
例如:一个多次滑屏的例子: action=TouchAction(driver) action.press(x=220,y=700).move_to(x=840, y=700).move_to(x=220, y=1530).move_to(x=840, y=1530).release().perform() 可以通过wait()等待操作 3.MultiAction()//多点触控 通过MultiAction().add()添加多个TouchAction操作,最后调用perform()一起执行这些操作 action0 = TouchAction().tap(el) action1 = TouchAction().tap(el) MultiAction().add(action0).add(action1).perform() 4.driver.swipe(x1, y1, x2, y2,duration) //从坐标(x1,x2)滑动到坐标(x2,y2),duration非必填项,滑动时间 (滑动的坐标不能超过屏幕的宽高) 可以通过【driver.get_window_size()】命令获得窗口高和宽,结果为{\'width\': 1080, \'height\': 1776} 一个鼠标向上下左右活动的例子如下: #获得屏幕大小宽和高
def getSize(driver):
x = driver.get_window_size()[\'width\']
y = driver.get_window_size()[\'height\']
return (x, y)
#屏幕向上滑动
def swipeUp(driver,t=1000):
l = getSize(driver)
x1 = int(l[0] * 0.5) #x坐标
y1 = int(l[1] * 0.75) #起始y坐标
y2 = int(l[1] * 0.25) #终点y坐标
driver.swipe(x1, y1, x1, y2,t)
#屏幕向下滑动
def swipeDown(driver,t=1000):
l = getSize(driver)
x1 = int(l[0] * 0.5) #x坐标
y1 = int(l[1] * 0.25) #起始y坐标
y2 = int(l[1] * 0.75) #终点y坐标
driver.swipe(x1, y1, x1, y2,t)
#屏幕向左滑动
def swipLeft(driver,t):
l=getSize(driver)
x1=int(l[0]*0.75)
y1=int(l[1]*0.5)
x2=int(l[0]*0.05)
driver.swipe(x1,y1,x2,y1,t)
#屏幕向右滑动
def swipRight(driver,t=1000):
l=getSize(driver)
x1=int(l[0]*0.05)
y1=int(l[1]*0.5)
x2=int(l[0]*0.75) driver.swipe(x1,y1,x2,y1,t) #调用向下滑动的方法 swipeDown(driver) 五、系统按键事件 press_keycode(AndroidKeyCode)//发送按键事件 例如:点击home键,home键的KeyCode是3 driver.press_keycode(3)
键名
描述
键值
KEYCODE_CALL
拨号键
5
KEYCODE_ENDCALL
挂机键
6
KEYCODE_HOME
按键Home
3
KEYCODE_MENU
菜单键
82
KEYCODE_BACK
返回键
4
KEYCODE_SEARCH
搜索键
84
KEYCODE_CAMERA
拍照键
27
KEYCODE_FOCUS
拍照对焦键
80
KEYCODE_POWER
电源键
26
KEYCODE_NOTIFICATION
通知键
83
KEYCODE_MUTE
话筒静音键
91
KEYCODE_VOLUME_MUTE
扬声器静音键
164
KEYCODE_VOLUME_UP
音量增加键
24
KEYCODE_VOLUME_DOWN
音量减小键
25
更多KeyCode可以查看下面的博客:
http://blog.csdn.net/crisschan/article/details/50419963
六、driver的一些比较重要操作
1.reset()
//重置app
这时候driver会重置,相当于卸载重装应用。所以本地缓存会失效
driver.reset()
2.start_activity(包名,activity名)
//启动app的某一个activity
例如:driver.start_activity("com.wuba.zhuanzhuan","./presentation.view.activity.LaunchActivity")
启动一个activity,这个activity必须是AndroidManifest.xml中有intent-filter的activity<
intent-filter>
<
action android:name="android.intent.action.MAIN"/>
<
category android:name="android.intent.category.LAUNCHER"/>
<
/intent-filter>
这种启动activity和driver的reset()不同的是
3.contexts
//获得所有contexts
driver.contexts
结果如下:
[\'NATIVE_APP\', \'WEBVIEW_com.android.browser\']
NATIVE_APP:native的context
WEBVIEW_com.android.browser:webview的context,存放html的容器
4.current_context
//查看当前的contextdriver.current_context
5.switch_to.context(context名)
//切换context
driver.switch_to.context("WEBVIEW_com.wuba.zhuanzhuan")
NATIVE时不能定位WEBVIEW的内容,在WEBVIEW的context时不能定位NATIVE的内容。
所以需要切换到对应的context中去进行操作
6.setNetworkConnection(bitmask掩码)
//设置网络类型
例如:设置网络类型为只开wifi
driver.set_network_connection(2)
网络的bitmask掩码如下:
| 值 (别名)
| 数据连接 | Wifi 连接 | 飞行模式 |
| ------------------ | ---- | ---- | ------------- |
| 0 (什么都没有)
| 0
| 0
| 0 |
| 1 (飞行模式)
| 0
| 0
| 1 |
| 2 (只有Wifi)
| 0
| 1
| 0 |
| 4 (只有数据连接)
| 1
| 0
| 0 |
| 6 (开启所有网络)
| 1
| 1
| 0 |
7.scroll(起始元素,结束元素)
driver.scroll(origin_el,destination_el)
8.获得当前页面的所有元素
driver.page_source
这可以用来判断元素是否存在,例如(assert
"发布成功"
in
driver.page_source)
9.补充一些driver启动时可能用到的项
其实这些在上一篇启动里都有介绍,但是有些可能大家没注意到的点再列一下。这些点也是我在测试中实际遇到的点
autoLaunch :Appium是否要自动启动或安装app,默认true
desired_caps[\'autoLaunch\']
=
\'false\'
有的时候我不想让appium每次都启动app,想自己去启动activity,那这个项这时就可以起作用了
noReset:在会话前是否重置app状态。默认是false
desired_caps[\'noReset\']
=
\'true\'
newCommandTimeout:设置未接收到新命令的超时时间,默认60s
如果60s内没有接收到新命令,appium会自动断开连接,如果我需要很长时间做driver之外的操作,可能延长接收新命令的超时时间
desired_caps["newCommandTimeout"]=1800
本文参考:https://www.cnblogs.com/meitian/p/6103391.html推荐阅读
- android不是内部或外部命令,也不是可执行的程序或批处理文件
- App 99.9%稳定
- Dapper+SqlServerCe部署
- spring整合mybatis之mapper开发
- Android 音视频深入 十八 FFmpeg播放视频,有声音(附源码下载)
- Android NDK pthreads详细使用
- app抓包,根据接口开发web端
- appium desktop连接模拟器
- Android adb你真的会用吗?