安卓自动化测试,贺晓聪之uiautomator设备和选择器~Python详解

简介: 1、设备对象引入uiautomator,获取设备对象语法:from uiautomator import device as dd 即为设备对象1.1、获取设备信息语法:d.info返回值:{ u'displayRotation': 0, u'displaySizeDpY': 6...

1、设备对象

引入uiautomator,获取设备对象<所谓设备对象可理解为:Android模拟器或者真机>

语法:from uiautomator import device as d

d 即为设备对象

1.1、获取设备信息

语法:d.info

返回值:

{ u'displayRotation': 0,
  u'displaySizeDpY': 640,
  u'displaySizeDpX': 360,
  u'currentPackageName': u'com.android.launcher',
  u'productName': u'takju',
  u'displayWidth': 720,
  u'sdkInt': 18,
  u'displayHeight': 1184,
  u'naturalOrientation': True
}

返回值解释如下:

displayRotation  0 代表竖屏 1 代表横屏

currentPackageName  当前的Activity的Package名字

productName  当前设备名称

displayWidth  当前设备屏幕宽度  当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,displayWidth 取值会和 displayHeight 互换

displayHeight 当前设备屏幕高度  当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,displayHeight 取值会和 displayWidth 互换

sdkInt 当前SDK版本

naturalOrientation 当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,取值为False,为竖屏状态时,取值为:True

1.2、点亮或熄灭屏幕(Turn on/off screen)

# Turn on screen
d.screen.on()
# Turn off screen
d.screen.off()
# wakeup the device
d.wakeup()
# sleep the device, same as turning off the screen.
d.sleep()

检查屏幕状态,关闭OR点亮?

if d.screen == "on":  # of d.screen != "off"
    # do something in case of screen on
    pass
if d.screen == "off":  # of d.screen != "on"
    # do something in case of screen off
    pass

1.3、系统常用按键

# press home key
d.press.home()
# press back key
d.press.back()
# the normal way to press back key
d.press("back")
# press keycode 0x07('0') with META ALT(0x02) on
d.press(0x07, 0x02)

下面的这些按键也是被支持的,如下:

Next keys are currently supported:

  • home                   #手机Home键
  • back                   #手机返回键
  • left                   #对应键盘上的向右键<-
  • right                  #对应键盘上的向右键->
  • up                    #对应键盘上的向上键
  • down                   #对应键盘上的向下键
  • center                  #选中?
  • menu                   #菜单
  • search                  #查找?
  • enter                  #对应键盘上的Enter键
  • delete(or del)                          #对应键盘上的DEL键 用于删除
  • recent(recent apps)                  #任务切换
  • volume_up                #声音向上调整
  • volume_down               #声音向下调整
  • volume_mute               #静音按键
  • camera                  #拍照
  • power                   #电源键

1.4、与设备交互(单击、长按、滑动(手势密码)、拖拽)

单击屏幕坐标点

# click (x, y) on screen
d.click(x, y)

长按屏幕坐标点

# long click (x, y) on screen
d.long_click(x, y)

在屏幕上滑动

# swipe from (sx, sy) to (ex, ey)
d.swipe(sx, sy, ex, ey)
# swipe from (sx, sy) to (ex, ey) with 10 steps
d.swipe(sx, sy, ex, ey, steps=10)

在屏幕上拖拽

# drag from (sx, sy) to (ex, ey)
d.drag(sx, sy, ex, ey)
# drag from (sx, sy) to (ex, ey) with 10 steps
d.drag(sx, sy, ex, ey, steps=10)

1.5、屏幕操作及屏幕方向获取与控制<上述:displayRotation  0 代表竖屏 1 代表横屏>,竖屏分为 natural(自然的,正常的竖屏) 和 upsidedown(倒过来的竖屏),横屏分为向左和向右两个方向,分别为:left 和 right 

设备属性:orientation 可能取得值为:

  • natural or n
  • left or l
  • right or r
  • upsidedown or u (can not be set)

说明:在手机设备上,倒过来的屏幕很少见,因此:d.orientation 取值 upsidedown 的可能性几乎没有

# retrieve orientation, it may be "natural" or "left" or "right" or "upsidedown" 获取设备屏幕方向如下:
orientation = d.orientation
# set orientation and freeze rotation.
# notes: "upsidedown" can not be set until Android 4.3.                          设置设备屏幕方向如下:
d.orientation = "l" # or "left"
d.orientation = "r" # or "right"
d.orientation = "n" # or "natural"

锁屏/解除锁屏

# freeze rotation
d.freeze_rotation() #锁屏
# un-freeze rotation
d.freeze_rotation(False) #解锁

截屏操作

# take screenshot and save to local file "home.png", can not work until Android 4.2.
d.screenshot("home.png")

打开通知或快速设置

# open notification, can not work until Android 4.3.
d.open.notification()
# open quick settings, can not work until Android 4.3.
d.open.quick_settings()

注意:(如果notification已经打开了,调用d.open.quick_settings()不会打开快速设置)

等待空闲或窗口更新(Wait for idle or window update)

# wait for current window to idle
d.wait.idle()
# wait until window update event occurs
d.wait.update()

2、uiautomator 选择器

选择器是在当前窗口中标识特定的UI对象。可理解为:UiObject对象

目前,在uiautomator中支持以下属性选择器:

text, textContains, textMatches, textStartsWith
className, classNameMatches
description, descriptionContains, descriptionMatches, descriptionStartsWith
checkable, checked, clickable, longClickable
scrollable, enabled,focusable, focused, selected
packageName, packageNameMatches
resourceId, resourceIdMatches
index, instance

下面依次进行解读:

2.1、text选择器(支持在uiautomator中Text属性不为空的元素)

例如:

具体用法如下:

d(text="Maps").click()
#当然也可以多个属性在一块使用
d(text="Maps",className="android.widget.TextView").click()
#或者
d(text="Maps",className="android.widget.TextView",packageName="com.google.android.apps.nexuslauncher").click()

总之:要尽可能的使用选择器唯一确定一个被选择对象(UiObject)

除了可以进行选择UiObject对象以外,我们亦可以使用选择器设置某些元素的值,如下:

#输入短信目标手机号
d(text="To").set_text("10086")
#如果本窗口中有多个text为To的元素,我们也可以使用多属性选择
d(text="To",packageName="com.google.android.apps.messaging").set_text("10086").set_text("10086")

textContains,textMaches,textStartsWith 分别代表:包含,正则表达式,以XXX开头等

例如:

d(text="Name").set_text("John")

d(textContains="ame").set_text("John")

d(textStartsWith="Nam").set_text("John")

2.2、className,classNameMatches 类选择器 及 descriptiondescriptionContainsdescriptionMatchesdescriptionStartsWith 描述选择器 及 packageNamepackageNameMatches 包选择器 及 resourceIdresourceIdMatches ResId选择器用法和text选择器类似,都可以多属性选择器结合在一起使用。

示例代码如下:

# To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView'
d(text='Clock', className='android.widget.TextView')
d(description="add new contact").click()
d(descriptionContains="new contact").click()
d(descriptionStartsWith="add new").click()
#resourceid选择器
d(resourceId="com.android.contacts:id/menu_save").click()
#text选择器
d(textStartsWith="Nam").set_text("John")
#描述选择器
d(descriptionContains="new contact").click()
#多属性结合
d(text="Name",className="android.widget.EditText").set_text("John")
#index选择器和child选择器
d(resourceId="com.android.settings:id/list").child(className="android.widget.LinearLayout", index=2).child(resourceId="android:id/widget_frame").child(resourceId="android:id/switch_widget").click()

在此,说明下child、sibling选择器和index选择器及instance选择器(严格讲instance不是选择器,仅仅只是在输出多个结果的情况下,可以通过索引(下标)进行选择)

首先说明child选择器,sibling选择器:分别可理解为:子选择器(可嵌套),兄弟姐妹选择器

如上图右边部分,从上到下层次分为四层,最后一层的两个元素可理解为兄弟姐妹,在此,我们如果要选择最下面的那个元素就可以用到child选择器及sibling选择器,当然,本人不建议使用孩子,兄妹选择器,如果能用其他方法实现,建议用其他方法:

在此,我写的方法如下:<没有具体验证,仅仅只是演示>

#孩子选择器及兄弟姐妹选择器的用法:child/sibling
d(resourceId="id/pager").child(className="android.widget.FrameLayout").child(resourceId="id/empty_view").child(resourceId="id/empty_image_hint").sibling(packageName="com.google.android.apps.messaging")

2.3、index选择器及instance,比较容易混淆的两个,一个是选择器,一个代表索引,如下:

index选择器对应uiautomator的index属性,如下:

其用法和text选择器大同小异,不过在此需要指出的是,有些窗体中index取值会发生改变,因此,能不用index选择器的,尽可能不用!

#index选择器
d(className="android.widget.LinearLayout", index=2).click()

instance 的用法:当你的选择器返回的结果不是指向唯一元素时(两个或者多个),你可以通过instance进行选择。

贺晓聪原文:

Multiple instances

Sometimes the screen may contain multiple views with the same e.g. text, then you will have to use "instance" properties in selector like below:

d(text="Add new", instance=0)  # which means the first instance with text "Add new"

However, uiautomator provides list like methods to use it.

# get the count of views with text "Add new" on current screen
d(text="Add new").count

# same as count property
len(d(text="Add new"))

# get the instance via index
d(text="Add new")[0]
d(text="Add new")[1]
...

# iterator
for view in d(text="Add new"):
    view.info  # ...

2.4、获取选定的UI对象状态及其信息(Get the selected ui object status and its information)

检测特定的UI对象是否存在(Check if the specific ui object exists)

两种写法,如下:

d(text="Settings").exists # True if exists, else False
d.exists(text="Settings") # alias of above property.

检索特定UI对象的信息(Retrieve the info of the specific ui object)

d(text="Settings").info

(结果为列表List),如下:

{ u'contentDescription': u'',
  u'checked': False,
  u'scrollable': False,
  u'text': u'Settings',
  u'packageName': u'com.android.launcher',
  u'selected': False,
  u'enabled': True,
  u'bounds': {u'top': 385,
              u'right': 360,
              u'bottom': 585,
              u'left': 200},
  u'className': u'android.widget.TextView',
  u'focused': False,
  u'focusable': True,
  u'clickable': True,
  u'chileCount': 0,
  u'longClickable': True,
  u'visibleBounds': {u'top': 385,
                     u'right': 360,
                     u'bottom': 585,
                     u'left': 200},
  u'checkable': False
}

设置/清除字段或编辑文本

d(text="Settings").clear_text()  # clear the text
d(text="Settings").set_text("My text...")  # set the text

执行单击特定的UI对象

# click on the center of the specific ui object
d(text="Settings").click()
# click on the bottomright corner of the specific ui object  单击右下方
d(text="Settings").click.bottomright()
# click on the topleft corner of the specific ui object   单击左上方
d(text="Settings").click.topleft()
# click and wait until the new window update  单击并等待窗体响应
d(text="Settings").click.wait()

长时间点击特定的ui对象,双击?

# long click on the center of the specific ui object
d(text="Settings").long_click()
# long click on the bottomright corner of the specific ui object 右下角
d(text="Settings").long_click.bottomright()
# long click on the topleft corner of the specific ui object 左上角
d(text="Settings").long_click.topleft()

将UI对象拖动到另一点

# notes : drag can not be set until Android 4.3.
# drag the ui object to point (x, y)
d(text="Settings").drag.to(x, y, steps=100)
# drag the ui object to another ui object(center)  拖拽到text='Clock'的对象位置上
d(text="Settings").drag.to(text="Clock", steps=50)

滑动UI对象

滑动分为四个方向:left ,right,top ,bottom 即:左滑动 右滑动 上滑动 及向下滑动

d(text="Settings").swipe.right()
d(text="Settings").swipe.left(steps=10)
d(text="Settings").swipe.up(steps=10)
d(text="Settings").swipe.down()

Two point gesture from one point to another

d(text="Settings").gesture((sx1, sy1), (sx2, sy2)) .to((ex1, ey1), (ex2, ey2))

Two point gesture on the specific ui object

Supports two gestures:

  • In, from edge to center
  • Out, from center to edge
# notes : pinch can not be set until Android 4.3.
# from edge to center. here is "In" not "in"
d(text="Settings").pinch.In(percent=100, steps=10)
# from center to edge
d(text="Settings").pinch.Out()

3 point gesture

d().gestureM((sx1, sy1), (sx2, sy2),(sx3, sy3)) \
                  .to((ex1, ey1), (ex2, ey2),(ex3,ey3))
d().gestureM((100,200),(300,200),(600,200),(100,600),(300,600),(600,900))

等到特定的UI对象出现或消失

# wait until the ui object appears
d(text="Settings").wait.exists(timeout=3000)
# wait until the ui object gone
d(text="Settings").wait.gone(timeout=1000)

在具体的UI对象执行甩(滚动)Perform scroll on the specific ui object(scrollable)

Possible properties:

  • horiz or vert
  • forward or backward or toBeginning or toEnd
# fling forward(default) vertically(default) 
d(scrollable=True).fling()
# fling forward horizentally
d(scrollable=True).fling.horiz.forward()
# fling backward vertically
d(scrollable=True).fling.vert.backward()
# fling to beginning horizentally
d(scrollable=True).fling.horiz.toBeginning(max_swipes=1000)
# fling to end vertically
d(scrollable=True).fling.toEnd()

Perform scroll on the specific ui object(scrollable)-在具体的UI对象执行甩(滚动)

Possible properties:

  • horiz or vert
  • forward or backward or toBeginning or toEnd, or to
# scroll forward(default) vertically(default)
d(scrollable=True).scroll(steps=10)
# scroll forward horizentally
d(scrollable=True).scroll.horiz.forward(steps=100)
# scroll backward vertically
d(scrollable=True).scroll.vert.backward()
# scroll to beginning horizentally
d(scrollable=True).scroll.horiz.toBeginning(steps=100, max_swipes=1000)
# scroll to end vertically
d(scrollable=True).scroll.toEnd()
# scroll forward vertically until specific ui object appears
d(scrollable=True).scroll.to(text="Security")

感谢贺晓聪的无私奉献,谢谢!

 

相关文章
|
2月前
|
Python
自动化微信朋友圈:Python脚本实现自动发布动态
本文介绍如何使用Python脚本自动化发布微信朋友圈动态,节省手动输入的时间。主要依赖`pyautogui`、`time`、`pyperclip`等库,通过模拟鼠标和键盘操作实现自动发布。代码涵盖打开微信、定位朋友圈、准备输入框、模拟打字等功能。虽然该方法能提高效率,但需注意可能违反微信使用条款,存在风险。定期更新脚本以适应微信界面变化也很重要。
234 61
|
3月前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
208 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
2月前
|
敏捷开发 测试技术 持续交付
自动化测试之美:从零开始搭建你的Python测试框架
在软件开发的马拉松赛道上,自动化测试是那个能让你保持节奏、避免跌宕起伏的神奇小助手。本文将带你走进自动化测试的世界,用Python这把钥匙,解锁高效、可靠的测试框架之门。你将学会如何步步为营,构建属于自己的测试庇护所,让代码质量成为晨跑时清新的空气,而不是雾霾中的忧虑。让我们一起摆脱手动测试的繁琐枷锁,拥抱自动化带来的自由吧!
|
3月前
|
运维 监控 网络安全
自动化运维的崛起:如何利用Python脚本简化日常任务
【10月更文挑战第43天】在数字化时代的浪潮中,运维工作已从繁琐的手工操作转变为高效的自动化流程。本文将引导您了解如何运用Python编写脚本,以实现日常运维任务的自动化,从而提升工作效率和准确性。我们将通过一个实际案例,展示如何使用Python来自动部署应用、监控服务器状态并生成报告。文章不仅适合运维新手入门,也能为有经验的运维工程师提供新的视角和灵感。
|
3月前
|
运维 监控 Python
自动化运维:使用Python脚本简化日常任务
【10月更文挑战第36天】在数字化时代,运维工作的效率和准确性成为企业竞争力的关键。本文将介绍如何通过编写Python脚本来自动化日常的运维任务,不仅提高工作效率,还能降低人为错误的风险。从基础的文件操作到进阶的网络管理,我们将一步步展示Python在自动化运维中的应用,并分享实用的代码示例,帮助读者快速掌握自动化运维的核心技能。
158 3
|
3月前
|
运维 监控 应用服务中间件
自动化运维:如何利用Python脚本提升工作效率
【10月更文挑战第30天】在快节奏的IT行业中,自动化运维已成为提升工作效率和减少人为错误的关键技术。本文将介绍如何使用Python编写简单的自动化脚本,以实现日常运维任务的自动化。通过实际案例,我们将展示如何用Python脚本简化服务器管理、批量配置更新以及监控系统性能等任务。文章不仅提供代码示例,还将深入探讨自动化运维背后的理念,帮助读者理解并应用这一技术来优化他们的工作流程。
|
3月前
|
运维 监控 Linux
自动化运维:如何利用Python脚本优化日常任务##
【10月更文挑战第29天】在现代IT运维中,自动化已成为提升效率、减少人为错误的关键技术。本文将介绍如何通过Python脚本来简化和自动化日常的运维任务,从而让运维人员能够专注于更高层次的工作。从备份管理到系统监控,再到日志分析,我们将一步步展示如何编写实用的Python脚本来处理这些任务。 ##
|
3月前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
263 1
|
3月前
|
JSON 测试技术 持续交付
自动化测试与脚本编写:Python实践指南
自动化测试与脚本编写:Python实践指南
86 1
|
4月前
|
运维 监控 网络安全
自动化运维的魔法:如何用Python简化日常任务
【10月更文挑战第9天】在数字时代的浪潮中,运维人员面临着日益增长的挑战。本文将揭示如何通过Python脚本实现自动化运维,从而提高效率、减少错误,并让运维工作变得更具创造性。我们将探索一些实用的代码示例,这些示例将展示如何自动化处理文件、监控系统性能以及管理服务器配置等常见运维任务。准备好让你的运维工作升级换代了吗?让我们开始吧!

热门文章

最新文章