网络知识 娱乐 uiautomator介绍

uiautomator介绍

执行背景

当前项目研发进度加快,模块化项目增加了模块功能的独立性,但同时也增加了版本之间的出现兼容问题的风险,怎样才能在当前快速迭代的环境中还能保持整体功能的稳定,正是眼前迫切需求。

uiautomator是什么?

功能介绍

uiautomator是Android官方推出的安卓应用界面自动化测试工具,是理想的针对APK进行自动化功能回归测试的利器。能够根据文本、控件id、坐标进行点击、长按、滑动、查找等操作,实现与人一致的手动操作逻辑,根据测试用例使用python编码后根据指定命令操作,检查预期结果,进行测试。最终通过单元测试执行用例脚本生成相应报告。

python环境下使用教程

1.python3环境

2.安装uiautomator

pip install uiautomator

3.导包

from uiautomator import Device 
 
d = Device('emulator-5554') # 设备名称,可通过adb devices查看获取

3.API介绍

1. 先看看常用的基本API
1.1 获取机器的信息
代码如下,

d.info

下面是可能的结果(因机器不同而异),

{u'displayRotation': 0, 
u'displaySizeDpY': 640, 
u'displaySizeDpX': 360, 
u'screenOn': True, 
u'currentPackageName': u'com.android.launcher3', 
u'productName': u'DeviceX', 
u'displayWidth': 720, 
u'sdkInt': 25, 
u'displayHeight': 1280, 
u'naturalOrientation': True}

1.2 屏幕相关的操作
开关屏幕,代码如下

# 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()

查看屏幕是否点亮,代码如下,

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)

还支持如下按键的操作,

home
back
left
right
up
down
center
menu
search
enter
recent(recent apps)
volume_up
volume_down
volume_mute
camera
power

更多按键定义,请移步至Android官网 AndroidKeyEvent
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 屏幕相关的操作
获取并设置屏幕的旋转方向,

# 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")

获取屏幕层级(hierachy)XML

# dump the widown hierarchy and save to local file "hierarchy.xml" 
d.dump("hierarchy.xml") 
# or get the dumped content(unicode) from return. 
xml = d.dump()

打开通知栏或快速设置栏,

# 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()

等待窗口休眠或更新,

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

2. Watcher
功能:开启守护进程,当符合条件时,完成特点的动作,如点击按钮等。
2.1 注册Watcher
示例一,

d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait").click(text="Force Close")

示例二,

d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait").press.back.home()
# Alternative way to define it as below
d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait").press("back", "home")
# d.watcher(name) ## creates a new named watcher.
#  .when(condition)  ## the UiSelector condition of the watcher.
#  .press.......()  ## press keys one by one in sequence.
#  Alternavie way defining key sequence is press(, ..., )

2.2 查看某个Watcher是否被触发

d.watcher("watcher_name").triggered 
# true in case of the specified watcher triggered, else false

2.3 移除某个Watcher

# remove the watcher 
d.watcher("watcher_name").remove()

2.4 列出所有已经注册的Watcher

d.watchers 
# a list of all registered wachers' names

2.5 查看是否有任何一个Watcher曾经被触发

d.watchers.triggered 
# true in case of any watcher triggered

2.6 复位所有已经被触发的Watcher

# reset all triggered watchers, after that, d.watchers.triggered will be false. 
d.watchers.reset()

2.7 移除Watcher

# remove all registered watchers 
d.watchers.remove() 
# remove the named watcher, same as d.watcher("watcher_name").remove() 
d.watchers.remove("watcher_name")

2.8 强制运行所有已经注册的Watcher

# force to run all registered watchers 
d.watchers.run()

3. Handler
和Watcher类似,但可以呼叫回调函数,示例代码如下,

def fc_close(device):
if device(text='Force Close').exists:
    device(text='Force Close').click()
return True  # return True means to break the loop of handler callback functions.

# turn on the handler callback function
d.handlers.on(fc_close)

# turn off the handler callback function
d.handlers.off(fc_close)

4. 选择器(Selector)
选择器(Selector)是用来识别当前屏幕的对象,它可以通过对象的下列属性来识别,

- 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

示例代码如下,

# To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView' 
d(text='Clock', className='android.widget.TextView')

4.1 通过父子关系选择

# get the child or grandchild 
d(className="android.widget.ListView").child(text="Bluetooth")

4.2 通过宗族关系选择

# get sibling or child of sibling 
d(text="Google").sibling(className="android.widget.ImageView")

4.3 通过相对位置选择,支持left/right/up/down,
示例代码如下,

## select "switch" on the right side of "Wi‑Fi" 
d(text="Wi‑Fi").right(className="android.widget.Switch").click()

4.4 检查当前屏幕UI对象是否存在

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

4.5 得到UI对象的信息

d(text="Settings").info

4.6 设置/清理可编辑文本的内容,

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

4.7 对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()

4.8 对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()

4.9 拖到UI对象到另外一个坐标或者另外一个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)
d(text="Settings").drag.to(text="Clock", steps=50)

4.10 滑动(swipe),支持四个方向,left/right/up/down,

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

4.11 双指操作,

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

4.12 双指操作,两手指往里捏(In),两手指往外捏(Out)

# 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()

4.13 三指手势

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))

4.14 等待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)

4.15 滑动操作,支持水平和垂直滑动,

# 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()

4.16 滚到操作,支持水平和垂直滚动

# 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")