写在前面
- Selector用于在当前窗口中标识特定的UI对象。选择之后可以对该对象进行相应操作。eg:
# 选择一个text未‘Clock’的对象,它的className是‘android.widget.TextView’
d(text='Clock', className='android.widget.TextView')
- Selector支持的参数
- text、textContains、textMatche、textStartsWith。(文本、文本包含、文本匹配、文本从开始匹配)
- className、classNameMatches
- description、descriptionContains、descriptionMatches、descriptionStartWith
- checkable、checked、clickable、longclickable
- scrollable、enabled、focusable、focused、selected
- packageName、packageNameMatches
- resourceID、resourceIdMatches
- index、instance
children and siblings
chilid():children,即当前控件的子控件
# 获取子控件或者孙子控件
# 先找到className=android.widget.ListView的控件,再找他的text=Bluetooth的子控件
d(className="android.widget.ListView").child(text='Bluetooth')
siblings():siblings,即兄弟姐妹控件
# 先找到text="Google"的控件,再找他的className="android.widget.ImageView"的兄弟姐妹控件
d(text="Google").sibling(className="android.widget.ImageView")
child_by_text()
# 1、先获取到className='android.widget.ListView'的控件
# 2、它的子控件通过text定位,参数里面直接写text的值,不用再写text=XX
d(className='android.widget.ListView', resourceId="android:id/list").child_by_text("Bluetooth",className="android.widget.LinearLayout")
# 允许通过滚动搜索子对象
d(className="android.widget.ListView", resourceId="android:id\list").child_by_text("Bluetooth", allow_scroll_search=True, className="android,widget.LinearLayout")
-
child_by_description()
查找某一控件的子孙们中具有特定description的子对象。其他参数以及用法和child_by_text()相似 -
child_by_instance()
在指定实例的子层次结构中的任意位置查找具有子UI元素的子元素。它在可见视图上执行而不滚动。 -
支持链式调用。举个🌰
<node index="0" text="" resource-id="android:id/list" class="android.widget.ListView" ...>
<node index="0" text="WIRELESS & NETWORKS" resource-id="" class="android.widget.TextView" .../>
<node index="1" text="" resource-id="" class="android.widget.LinearLayout" ...>
<node index="1" text="" resource-id="" class="android.widget.RelativeLayout" ...>
<node index="0" text="Wi‑Fi" resource-id="android:id/title" class="android.widget.TextView" .../>
</node>
<node index="2" text="ON" resource-id="com.android.settings:id/switchWidget" class="android.widget.Switch" .../>
</node>
...
</node>

比如我们要单击TextView-'Wi-Fi’右侧开关小部件,首先要找到这个开关小部件然后选择。但是根据UI层次结果,存在多个开关小部件,而且几乎具有相同的属性。如果但按照className选择将不起作用。这时候我们就可以使用child()方法或者siblings()方法
d(className="android.widget.ListView",resourceId="android:id/list").child_by_text("Wi-Fi", className="android.widget.LinearLayout").child(className="android.widget.Switch").click()
- 相对定位
可以使用left、right、top、bottom这些相对定位来找到元素
d(A).left(B) # 选择A左方的B
d(A).right(B) # 选择A右方的B
d(A).up(B) # 选择A上方的B
d(A).down(B) # 选择A下方的B
因此对于上面的例子,我们也可以这样操作
# 选择"Wi-Fi"右方的"switch"
d(text="Wi-Fi").right(className="android.widget.Switch").click
- 多个对象的情况
- 1、在方法中使用instance传参的方式来获取多个相同属性元素中的指定元素。
d(text="Add new", instance=0) # 表示第一个text="Add New"的元素对象
- 2、uiautomator2也提供了类似列表的API
# 获取当前屏幕text="Add new"的元素数
d(text="Add new").count
# 获取当前屏幕text="Add new"的元素数
len(d(text="Add new"))
# 通过index获取指定的元素
d(text="Add new")[0]
d(text="Add new")[1]
# 迭代器
for view in d(text="Add new"):
view.info
Tip:在遍历结果列表的代码块中使用选择器时,必须确保屏幕的UI元素保持不变。否则当元素未找到时,在遍历列表时可能会发生错误。
获取所选对象的状态及信息
- 检查特定对象是否存在
d(text="Settings").exists # 如果元素存在,返回True,如果元素不存在,返回False
d.exists(text="Settings") # 等价于上面方法。如果元素存在,返回True,如果元素不存在,返回False。
d(text="Settings").exists(timeout=3) # 等待3s,如果3s内出现指定元素,则返回True,否则返回False。
d.exists(text="Setting").wait(3) # 等价于上面方法
- 检索所选元素的信息
d(text="Settings").info
可能的输出:
{
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
}
- 获取/设置/清除 可编辑字段的文本(例如:EditText小部件)
d(text="Settings".get_text()) # 获取text="Setting"该部件的文本
d(text="Settings").set_text("My text...") # 设置text="Setting"该部件的文本
d(text="Settings").clear_text() # 清除text="Setting"该部件的文本
- 获取部件的坐标
x, y = d(text="Settings").center()
# x, y = d(text="Settings").center(offset=(0, 0)) # 获取部件左上角坐标
- 截图指定的小部件
im = d(text="Settings").screenshot()
im.save("settings.jpg")
click操作
- 点击特定对象
# 点击特定元素中心
d(text='Settings').click()
# 等待元素最多10s, 然后进行点击操作
d(text='Settings').click(timeout=10)
# 默认点击元素中心
d(text='Settings').click(offset=(0.5,0.5))
# 点击元素左上角
d(text='Settings').click(offset=(0,0))
# 点击元素右下角
d(text='Settings').click(offset=(1,1))
# 等待元素最多10s,如果10s内等到元素出现,则进行点击
clicked = d(text='Skip').click_exists(timeout=10.0)
# 等待元素消失,返回bool
is_gone = d(text='Skip').click_gone(maxretry=10, interval=1.0) # maxretry为最大重试次数,默认值10,间隔默认值1.0
- 长按特定元素
# 在特定元素中心长按
d(text="Settings").long_click()
特定UI对象的手势操作
darg_to(坐标或元素,等待时间):将指定元素拖向一个点或另一个元素
Tip:drag操作在安卓4.3版本下不可用
# 在0.5s内 将指定元素拖动到指定坐标
d(text="Settings").drag_to(x, y, duration=5)
# 在0.25s内将指定元素拖动到另一个指定元素的中心位置
d(text="Settings").drag_to(text="Clock", duration=0.25)
swipe("方向",时间):从特定元素的中心滑到其边缘
滑到支持的四个方向:left、right、top、bottom
# Tips:1steps大概是5ms,所以20steps大概是0.1s
d(text="Settings").swipe("right")
d(text="Settings").swipe("left", steps=10)
d(text="Settings").swipe("up", steps=20)
d(text="Settings").swipe("down",steps=20)
gesture(第一个点坐标终点值,第二个点坐标终点值,第一个点坐标起始值,第二个点坐标起始值):从一个划向另一个点的两点手势(安卓4.3版本以下不支持)
d(text="Settings").gesture((sx1,sy1),(sx2,sy2),(ex1,ey1),(ex2,ey2))
- 特定元素上的两点手势
- 支持的两种手势
- 1、从边缘到中心
pinch_In(百分比,时间) - 2、从中心到边缘
pinch_out(百分比,时间)
# 从边缘到中心 注意:这里是“In”不是“in”
d(text="Settings").pinch_In(percent=100, steps=10)
# 从中心到边缘
d(text="Settings").pinch_out()
wait(timeout=时间):在指定时间内等待特定元素出现wait_gone(time_out=时间):在指定时间内等待特定元素消失
Tip:timeout默认为20s
# 等待元素出现
d(text="Settings").wait(timeout=3.0) # 返回一个bool值,如果3s内找到了该指定元素,返回True,否则返回False
# 等待元素消失
d(text="Settings").wait_gone(timeout=1.0) # 返回一个bool值,如果1s内元素消失,即找不到,返回True,否则返回False
- 对特定元素执行滚动(可滚动)
可能的属性:
1、horiz或者vert(水平或垂直)
2、forward或backward或toBeginning或toEnd(向前的、向后的、往开始、往终点)
# 如果不填参数,默认是垂直和向前的
d(srollable=True).fling()
# 向前垂直
d(srollable=True).fling.horiz.forward()
# 向后水平
d(srollable=True).fling.vert.backward()
# 水平回到起点
d(srollable=True).fling.horiz.toBeginning(max_swipes=1000)
# 滚动至终点
d(srollable=True).fling.toEnd()
-
在特定的元素上执行滚动(可滚动时)
-
可能的属性
-
1、horiz 或者 vert (水平或者垂直)
-
2、forward 或 backward 或 toBeginning 或toEnd 或 to (向前、向后、向起点、向终点、向任意方向)
# 默认垂直向前
d(scrollable=True).scroll(steps=10)
# 在100s内时间 水平向前
d(scrollable=True).scroll.horiz.forward(steps=100)
# 垂直向后
d(scrollable=True).scroll.vert.backward()
# 在100s时间内 垂直向起点,最大步数为1000
d(scrollable=True).scroll.horiz.toBeginning(steps=100, max_swipes=1000)
# 滚动至终点
d(scrollable=True).scroll.toEnd()
# 滚动至指定元素
d(scrollable=True).scroll.to(text="Security")
本文详细介绍了 Android UI 自动化测试中 Selector 的使用,包括文本、类名、描述等选择器参数,以及如何通过 child()、siblings() 方法进行子控件和兄弟控件的操作。此外,还涵盖了相对定位、手势操作、滚动操作等,并展示了点击、长按、文本获取与设置等交互功能。内容深入浅出,是进行 Android 应用自动化测试的重要参考。

633

被折叠的 条评论
为什么被折叠?



