Android自动化框架uiautomator简介

UI自动化测试框架,安卓移动端APP.
要求:Android 4.3以上
1.提供一系列API:执行UI测试在系统或者第三方APP上面;
2.允许在被测设备上执行操作,比如打开系统设置菜单。
3.适合编写黑盒自动化测试
UIautomator框架主要特点:
1.元素定位:UIautomator viewer。扫描、分析待测应用的UI组件的图像工具;
2.元素操作:Accessing devicestate.在目标设备和app上的各种操作
3.元素识别:UI Automator APIs,在多个应用程序中捕获和操作UI组件。
 
1.uiautomatorviewer
uiautomatorviewer位于sdk/tools目录下,可以扫描、分析待测试应用界面,分析结果可以导出为xml与截图。通过该工具可以分析出UI控件的id,text,focusable等等各种属性,甚至布局上的层次关系。
windows下运行tools下的uiautomatorviewer.bat
liunx下运行./uiautomatorviewer  启动该工具。
上图uiautomatorviewer的运行截图,左上角两个手机模样的图标点击后就会开始截图并分析UI组件,分析后的结果如下方所示, 左侧为手机当前画面截图,右侧上部为view控件的层次关系,下部为当前选中控件的各种信息。

2.uiautomator APIs

uiautomator是一个包含一套UI测试API,和支持运行测试程序的JAR包。该JAR包位于sdk/platforms/android-* /uiautomator.jar. 使用时需要注意自己的SDK版本需要大于16, SDK Tools版本需要大于21.Android版本需要高于4.3。
UIautomator有比较多的类。这里只介绍我们在APP自动化测试中常用的三种。其中UiSelector类是在appium定位元素时会用到的类。
UiSelector类

一、UiSelector作用

  按照一定的条件(例如控件的text值,资源id),定位界面上的元素。UiSelector对象的最终目的是去构造一个UiObject对象。

 

二、元素定位

 

1、根据text定位:

函数返回值 函数体 说明 用法
UiSelector text(String text) 根据“控件text属性的内容”构造出UiSelector对象 例如,一个控件text的值是“发现”,UiSelector s = new UiSelector().text("发现");
UiSelector textContains(String text) 根据“控件text属性包含的内容”构造出UiSelector对象 同上例子:UiSelector s = new UiSelector().textContains("现");
UiSelector textMatches(String regex)  根据“控件text属性正则表达式的内容”构造出UiSelector对象 正则表达式语法参考网上资料即可。
UiSelector textStartsWith(String text) 根据“控件text属性开始的内容”构造出UiSelector对象 同上例子:UiSelector s = new UiSelector().textStartsWith("发");

比较常用,准确度也比较高,中文查找的时候,有时候text元素是中文的,比如例如,一个控件text的值是“发现”,UiSelector s = new UiSelector().text("发现");此时运行的时候可能会报错 “UiOjbectNotFoundException” ,这时候只要把项目的编码格式改为utf-8就可以了。

 

2、根据description构造:

UiSelector description(String desc) 根据“控件content-desc属性的内容”构造出UiSelector对象
UiSelector descriptionContains(String desc) 包含**
UiSelector descriptionMatches(String regex) 正则
UiSelector descriptionStartsWith(String desc) 以**开始

同text的用法基本一致,也是比较靠谱的一种方式。

 

3、根据资源id:

UiSelector resourceId(String id) 根据资源id获取对象,例如:UiSelector s = new UiSelector().resourceId("com.tencent.mm:id/b8m")
UiSelector resourceIdMatches(String regex) 根据资源id的正则表达式获取对象

 

4、根据类:

  1)UiSelector className(String  className):

  根据控件的类名来找到UiSelector对象。如图

  

  这时候会出现问题:

  因为一般Android布局的时候,同样的控件类名都是一样的。

  因此我在微信的登录界面调用: UiSelector s = new UiSelector().className("android.widget.TextView"),它得到的就是我左上开始算第一个class名称为“android.widget.TextView”的控件。

  2)UiSelector instance (int instance):

  上面提到的假如我们想获取屏幕上电话号码的那个TextView使用这样方法,就可以使用instance:

  UiSelector s = new UiSelector().className("android.widget.TextView").instance(1);

  3)UiSelector index(int index):

  用法和上面的instance差不多,谷歌的原文说这个方法是unreliable的,推荐使用instance方法。

  4)UiSelector childSelector(UiSelector selector):

  有的时候假如子控件不好获得,而其父控件比较好获得的时候,我们通常采用这样的方式,例如下面:

  

  如图,LinearLayout就是ImageView和EditText的父控件,当子空间text、resource-id为空的时候,这种时候子控件定位比较困难。很明显,父控件id已经给定,那我们就可以先定位到父控件,再定位到子控件这种方法。

  在它的父控件的childSelector方法中传入一个带有一定特征的UiSelector对象,即可得到子控件  

  UiObject wx_input= new UiObject(new UiSelector().className("android.widget.RelativeLayout").childSelector(new UiSelector().className("android.widget.EditText")));   

  5)UiSelector fromParent(UiSelector selector):

  有的时候父控件也不好获得,而是同级的控件(同属一个parent)比较好获取,那么使用这样方法,还拿上面的举例:

  我们先得到EditText的UiSelector对象:UiSelector s1 = new UiSelector().resourceId("com.tencent.mm:id/axc");

  得到和它同样一个父控件的ImageView的UiSelector对象:UiSelector s2 = fromParent( new UiSelector().className("android.widget.ImageView") );

 

更多详情见:https://developer.android.com/reference/android/support/test/uiautomator/UiSelector.html

 

 UiObject类:安卓组件对象,类似于webdriver中的webelement队形,提供了元素的属性获取和元素的各种操作。对象有许多模拟实际操作手机的方法和属性。比如文本的编辑、点击、输入、手势操作等。

1、点击与长按

(1)相关API

 

返回值 API 说明
boolean click() 点击对象
boolean clickAndWaitForNewWindow(long timeout) 点击对象,等待新窗口出现,参数为等待超时时长
boolean clickAndWaitForNewWindow() 点击对象,等待新窗口出现
boolean clickBottomRight() 点击对象的右下角
boolean clickTopLeft() 点击对象的左上角
boolean longClick() 长按对象,对对象执行长按操作
boolean longClickBottomRight() 长按对象的右下角
boolean longClickTopLeft() 长按对象的左上角

 

 

(2)示例

new UiObject(new Selector().resourceId("xxxxx")).click();//对指定资源id的组件执行点击操作

2、拖拽与滑动
(1)区别
拖拽:将控件从当前位置移动到指定位置
滑动:向某一方向(上、下、左、右)移动一小段距离

(2)相关API

返回值 API 说明
boolean dragTo(UiObject destObj, int steps) 拖拽对象到另一个对象位置上,步长可设置拖动的速度
boolean dragTo(int destX, int destY, int steps) 拖拽对象到屏幕某个坐标位置上,步长可设置拖动速度
boolean swipeDown(int steps) 拖动对象往下滑动
boolean swipeLeft(int steps) 拖动对象往左滑动
boolean swipeRight(int steps) 拖动对象往右滑动
boolean swipeUp(int steps) 拖动对象往上滑动

 

3、输入文本与清除文本

(1)相关API

返回值 API 说明
boolean setText(String text) 在对象中输入文本(实现方式:先清除文本再输入)
void clearTextField() 清除编辑框中的文本(实现方式:长按再清除)

 

(2)补充说明

clearTextField()的内部实现方式是先长按文本框然后全选删除,导致有些编辑框无法通过调用该方法清除文本内容。这时最好自己写代码实现清除文本功能。

示例代码:

//将光标移动到行尾,使用backspace进行逐个删除

UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_MOVE_END);

//判断条件中w是编辑框为空时所显示的hint文本对象;当hint出现时,说明该编辑框内的文本已清空

while(!w.exists()){
UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_DEL);
}

4、获取对象的属性与属性的判断

 

(1)获取对象的属性-相关API

返回值 API 说明
Rect getBounds() 获得对象矩形坐标,矩形左上角坐标与右下角坐标
int getChildCount() 获得下一级子类数量
String getClassName() 获得对象类名属性的类名文本
String getContentDescription() 获得对象的描述属性的描述文本
String getPackageName() 获得对象包名属性的包名文本
String getText() 获得对象的文本属性中的文本
Rect getVisibleBounds() 返回可见视图的范围,如果视图的部分是可见的,只有可见部分报告的范围


(2)获取父类与子类节点-相关API

 

返回值 API 说明
UiObject getChild(UiSelector selector) 获得对象的子类对象,可以递归获取子孙当中某个对象
UiObject getFromParent(UiSelector selector) 从父类获取子类,按照UiSeletor获取兄弟类(递归)

 

 

(3)属性的判断-相关API

返回值 API 说明
boolean isCheckable() 检查对象的checkable属性是否为true
boolean isChecked() 检查对象的checked属性是否为true
boolean isClickable() 检查对象的clickable属性是否为true
boolean isEnabled() 检查对象的enabled属性是否为true
boolean isFocusable() 检查对象的focusable属性是否为true
boolean isFocused() 检查对象的focused属性是否为true
boolean isLongClickable() 检查对象的longclickable属性是否为true
boolean isScrollable() 检查对象的scrollable属性是否为true
boolean isSelected() 检查对象的selected属性是否为true

 

5、手势的操作

 

(1)手势相关操作
两指平移 
多指平移 
两指合拢 o---> <---o
两指扩张 <---oo--->

(2)相关API

返回值 API 说明
boolean performMultiPointerGesture(PointerCoords[]... touches) 执行单手指触控手势,可定义任意手势,与形状

boolean

performTwoPointerGesture(Point startPoint1, Point startPoint2, 
Point endPoint1, Point endPoint2, int steps)

执行任意两个手指触控手势,模拟两个手指手势
boolean pinchIn(int percent, int steps) 手势操作,两点向内收缩
boolean pinchOut(int percent, int steps) 手势操作,两点向外张开

 

6、判断对象是否存在

(1)相关API

返回值 API 说明
boolean waitForExists(long timeout) 等待对象出现
boolean waitUntilGone(long timeout) 等待对象消失
boolean exists() 检查对象是否存在

UiDevices类:提供了一些列方法和属性来模拟在手机上的实际操作,获取设备信息:屏幕分辨率、选装状态、亮屏、灭屏...操作:按键、坐标操作、滑动、拖拽、截图

一、UiDevice类简介

1、UiDevice代表设备状态。如屏幕的大小、旋转方向、按压各种按键等。

2、UiDevice为单例模式,可有2种方式获取其实例。

(1)UiDevice.getInstance();--->推荐
(2)getUiDevice.pressHome();---->在类A中封装方法,方法被类B调用的时候会出现空指针异常

3、主要功能
(1)获取设备信息:屏幕分辨率、选装状态、亮灭屏......
(2)操作:按键、坐标操作、滑动、拖拽、截图......
(3)监听器功能

二、按键与KEYCODE使用

 

1、点击按键 相关API

UiDevice实例调用以下方法即可实现点击按键操作。

 

 

返回值 方法名 描述
boolean pressBack() 模拟短按返回back键
boolean pressDPadCenter() 模拟按轨迹球中点按键
boolean pressDPadDown() 模拟轨迹球向下按键
boolean pressDPadLeft() 模拟轨迹球向左按键
boolean pressDPadRight() 模拟轨迹球向右按键
boolean pressDPadUp() 模拟轨迹球向上按键
boolean pressDelete() 模拟短按删除delete按键
boolean pressEnter() 模拟短按回车键
boolean pressHome() 模拟短按HOME键
boolean pressKeyCode(int keyCode, int metaState) 模拟短按键盘代码keycode
boolean pressKeyCode(int keyCode) 模拟短按键盘代码keycode
boolean pressMenu() 模拟短按menu键
boolean pressRecentApps() 模拟短按最近使用程序
boolean pressSearch() 模拟短按搜索键

 


2、KEYCODE 键盘映射码

(1)KeyEvent:按键事件,每个键盘映射码都保存在keyEvent的常量中。

(2)META Key

<1>辅助功能键: ALT、SHIFT、CAPS_LOCK

<2>辅助功能键的状态

 

  激活状态 metaState
base META_key未被激活 0
caps SHIFT或CAPS_LOCK被激活时 1
fn ALT被激活 2
caps_fn ALT,SHIFT或CAPS_LOCK同时被激活时 3

 

<3>示例

UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_A);//点击输入小写字母a
UiDevice.getInstance().pressKeyCode(KeyEvent.KEYCODE_A,1);//点击输入大写字母A

三、获取坐标与坐标点击

 

 1、坐标相关知识

(1)手机屏幕坐标:从左上角(0,0)开始到右下角(X,Y)
(2)dp:设备独立像素,例如,320像素显示到640像素上要拉伸一倍
(3)Point:代表一个点(x,y)

2、坐标相关API

UiDevice实例调用以下方法即可实现获取坐标和点击操作。
返回值 方法名 描述
boolean click(int x, int y) 使用坐标点击屏幕
int getDisplayHeight() 获取屏幕高度
Point getDisplaySizeDp() 获取显示尺寸返回显示大小(设备独立像素);屏幕旋转返回的显示大小调整
int getDisplayWidth()

获得屏幕宽度

 

3、Uiautomator Viewer

(1)功能:获取屏幕快照,并通过快照获取到控件的属性。

(2)启用方式

方式一、启动路径:adt/sdk/tools/UiautomatorViewer 

方式二、Eclipse/DDMS/Devices/UiautomatorViewer 

 

(3)屏幕快照参数之控件坐标

 通过UiautomatorViewer获取屏幕快照,选中目标控件,通过Node Detail / bounds[左上角顶点坐标][右下角顶点坐标] 可获取到控件的位置。



4、示例

(1)

UiDevice.getInstance().click(399,355);//点击[399,355]坐标点

(2)
int h = UiDevice.getInstance().getDisplayHeight();
int w = UiDevice.getInstance().getDisplayWidth();
UiDevice.getInstance().click(w/2,h/2); //点击屏幕的中心点

(3)

UiObject object = new UiObject(new UiSelector.resoutceId("com.andr....控件Id"));//根据ID获取控件

Rect r = object.getBounds();//获取控件对应的矩形区域相关属性
r.left; //矩形左上角顶点X坐标
r.top; //矩形左上角顶点Y坐标
r.right; //矩形右下角顶点X坐标
r.bottom; //矩形右下角顶点Y坐标
r.centerX(); //矩形的中心点X坐标
r.centerY(); //矩形的中心点Y坐标

四、拖拽与滑动

1、相关概念
(1)拖拽:将一个组件从一个坐标移动到另一个坐标处。
(2)滑动:手指从一个坐标点移动到另一个坐标点。
(3)步长:从一点滑动到另一点使用的时间,步长越短说明移动越快。

2、拖拽与滑动相关API

 

返回值 方法名 描述
boolean drag(int startX, int startY, int endX, int endY, int steps) 拖动对象从一个坐标拖动到另一个坐标,step表示拖拽过程使用的时间(ms)
boolean swipe(Point[] segments, int segmentSteps) 在点阵列中滑动,5ms一步
boolean swipe(int startX, int startY, int endX, int endY, int steps) 通过坐标滑动屏幕

 


3、示例:按照一个矩形的路径滑动
 Point p1 = new Point();
 Point p2 = new Point();
 Point p3 = new Point(); 
 Point p4 = new Point();
 p1.x =277;
 p1.y =318; 
 ...... //设置四个顶点的横纵坐标
 Point[] pp = {p1,p2,p3,p4};
 UiDevice.getInstance().swipe(pp,50); //每50毫秒走一步(从一个点滑动到下一个点)

五、旋转屏幕

1 、旋转屏幕相关知识
(1)旋转方向:4个方向,分别为 0度,90度,180度,270度
(2)重力感应器
(3)固定位置与物理旋转
固定位置:屏幕的方向固定在0、90、180、270度;
物理旋转:与重力感应器连接,关闭了物理旋转就是关闭了重力感应器。

2、屏幕旋转相关API

 

返回值 方法名 描述
void setOrientationLeft() 通过禁用传感器,然后模拟设备向左转,并且固定位置
void setOrientationNatural() 通过禁用传感器,然后模拟设备转到其自然默认的方向,并且固定位置
void setOrientationRight() 通过禁用传感器,然后模拟设备向右转,并且固定位置
void unfreezeRotation() 重新启用传感器和允许物理旋转
boolean isNaturalOrientation() 检测设置是否处于默认旋转状态
int getDisplayRotation() 返回当前的显示旋转,0度,90度,180度,270度值分别为:0(Surface.ROTATION_0)、1(Surface.ROTATION_90)、2(类推)、3(类推)
void freezeRotation() 禁用传感器和冻结装置物理旋转在其当前旋转状态

 


六、灭屏与唤醒

灭屏与唤醒相关API

返回值 方法名 描述
void wakeUp() 模拟按电源键,如果屏幕是唤醒的没有任何作用
void sleep() 模拟按电源键,如果屏幕已经是关闭的则没有任何作用
boolean isScreenOn() 检查屏幕是否亮屏

 

七、截图与等待空闲

 

1 、截图与等待空闲相关知识
(1)图片缩放比例:如缩小1/2,即将100*100px的图片长宽都缩小为原来的1/2,50*50px。
(2)图片质量:一般是指图片的大小,质量越高图片越大。
(3)File 类:文件或者文件夹。
(4)图片格式 :截图的格式都是PNG。
(5)空闲状态:窗口没有更新或界面无动作。
(6)窗口更新事件。

2、截图相关API

 

返回值 方法名 描述
boolean takeScreenshot(File storePath) 把当前窗口截图并将其存储为png默认1.0f的规模(原尺寸)和90%质量,参数为file类的文件路径。
boolean takeScreenshot(File storePath, float scale, int quality) 把当前窗口截图为png格式图片,可以自定义缩放比例与图片质量。

 

参数说明:
storePath:存储路径,必须为png格式。
scale:缩放比例,1.0为原图。
quality:图片压缩质量,范围为0-100。

3、等待空闲相关API

 

返回值 方法名 描述
void waitForIdle(long timeout) 自定义超时等待当前应用处于空闲状态
void waitForIdle() 等待当前应用处于空闲状态,默认等待10s;即10s后还不处于空闲状态则报错,程序在该句代码处中断;10s内程序处于空闲状态,则该句代码执行完毕。
boolean waitForWindowUpdate(String packageName, long timeout) 等待窗口内容更新事件的发生

 

 

八、获取包名&开启通知栏&快速设置&获取布局文件

 

1、相关知识
包名:应用的唯一标识。
通知栏:从手机顶部下滑,出现的下拉界面即通知栏。
快速设置:即通知栏中的快速设置控件,快速设置界面可设置网络、屏幕亮度、飞行模式等。

2、相关API
返回值 方法名 描述
void getCurrentPackageName() 获取当前界面的包名,即目前处于手机前台的应用的包名
void dumpWindowHierarchy(String fileName) 获取当前界面的布局文件,fileName给布局文件命名如“layout.xml”,保存在/data/local/tmp/目录下
boolean openNotification() 打开通知栏
boolean openQuickSettings() 打开快速设置

 

 更多具体用法见官方文档:https://developer.android.google.cn/training/testing/ui-automator#ui-automator-apis

posted @ 2022-08-09 17:50  陈晓猛  阅读(3588)  评论(0编辑  收藏  举报