uiautomator2-App内操作之Selector

本文详细介绍了 Android UI 自动化测试中 Selector 的使用,包括文本、类名、描述等选择器参数,以及如何通过 child()、siblings() 方法进行子控件和兄弟控件的操作。此外,还涵盖了相对定位、手势操作、滚动操作等,并展示了点击、长按、文本获取与设置等交互功能。内容深入浅出,是进行 Android 应用自动化测试的重要参考。

写在前面

  • 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")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值