《软件测试技术实战 设计、工具及管理》联载-37

简介: 《软件测试技术实战 设计、工具及管理》联载-37

11.1.4 UiAutomator API详解


介绍完UiAutomator如何配置,接下来介绍UiAutomatorAPI。图11-43UiAutomator的类的调用图。


image.png

11-43  UiAutomator的类图


1UiDevice类介绍

1)获取UiDevice实例的方式[J1]

  •  UiDevice.getInstance()[J2]
  •  getUiDevice()

注:第二种方式为获取UiDevice实例,当含有该实例的类被别的类调用时,会报空指针错误。所以一般仅用第一种方式。

 

案例11-1:获取UiDevice实例的两种方式。
package com.uiautomatortest;
import android.os.Bundle;
import android.os.RemoteException;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class TestGetUiDevice2 extends UiAutomatorTestCase {
        public void testDevice(){
                TestGetUiDevice device1=new GetUiDevice();
        device1.press();
    }
public static void main(String[] args){
        String jarName,testClass,testName,androidId;
        jarName="DemoTest";
        testClass="com.uiautomatortest.Test";
        testName="testDevice";
        androidId="1";
        new UiAutomatorHelper(jarName,testClass,testName,androidId);
    }
}


TestGetUiDevice2里调用类TestGetUiDevice1中包含getUiDevice()press方法时报空指针错误:java.lang.NullPointerException


如果将TestGetUiDevice1.java中的getUiDevice()换成UiDevice.getInstance(),则可以正常运行。修改后的TestGetUiDevice1.java如下:


package com.uiautomatortest;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class TestGetUiDevice1 extends UiAutomatorTestCase {
    public void press(){
//        getUiDevice().pressMenu();
//        getUiDevice().pressHome();
        UiDevice.getInstance().pressMenu();
        UiDevice.getInstance().pressHome();
            }
}


所以,都是采用UiDevice.getInstance()方式获取UiDevice实例。


2UiDevice功能[J3]

获取设备信息:屏幕分辨率、旋转状态、亮灭屏幕状态等。

操作:按键、坐标操作、滑动、拖拽、灭屏唤醒屏幕、截图等。

监听功能。

手机常见按键如下:

HOME:主屏幕键。

MENU:菜单键。

BACK:返回键。

VOLUME_UP:音量加键。

VOLUME_DOWN:音量减键。

RecentApps:最近使用APP

POWER:电源键。

Dpad:上下左右。

UiDevice按键API说明见表11-1


11-1                                                  UiDevice按键API说明

返回值

方法名      

描述

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

模拟按搜索键

 

案例11-2UiDevice按键API
package com.uiautomatortest;
import android.os.Bundle;
import android.os.RemoteException;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class Test extends UiAutomatorTestCase {
    public void testHome (){
        UiDevice.getInstance().pressHome();
        Sleep(2000);
    }
    public void testMenu(){
        UiDevice.getInstance().pressMenu();
        Sleep(2000);
    }    
    public void testRecent() throws RemoteException{
        UiDevice.getInstance().pressRecentApps();
        Sleep(2000);
    }
}


3KEYCODE键盘映射码,包括:

KeyEvent:按键事件。

META KEY

辅助功能键:ALTSHIFTCAPS_LOCK

KEYCODE键盘映射码见表11-2


11-2                                                   KEYCODE键盘映射码

激活状态

metaState

base

META_key未被激活

0

caps

ShiftCaps Lock被激活

1

fn

Alt被激活

2

caps_fn

AltShiftCaps Lock同时被激活

3

 

案例11-3KEYCODE键盘映射码。
public void testKeyCode (){
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_A); //小写a
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_B); //小写b
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_C); //小写c
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_A,1); //大写A
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_B,1); //大写B
        UiDevice.getInstance ().pressKeyCode(KeyEvent.KEYCODE_C,1); //大写C
    }


4)在Eclipse中如何查看一个Android模拟器的内部文件[J4]

需要进行UiAutomator测试,往往需要知道系统中含有哪些应用程序包以及包的名称,可以在Eclipse中添加DDMS工具来查看,如图11-44所示。


2.坐标相关的知识

手机屏幕坐标:左上角开始到右下角结束。

DP:设备独立像素,如320像素显示到640像素上要拉伸一倍。

Point:代表一个点(xy),左上角的坐标永远为(00)

1)坐标相关API见表11-3


image.png

11-44  Eclipse中添加DDMS工具


11-3                                                           坐标相关API

返回值

方法名

描述

boolean

Click(int x,int  y)

使用坐标点击屏幕

int

getDisplayHeight()

获取屏幕高度

Point

getDisplaySizeDP()

获取显示尺寸,返回显示大小(设备独立像素)

屏幕旋转返回的显示大小调整

int

getDisplayWidth()

获取屏幕宽度

 

2)使用UiAutomator Viewer获取屏幕快照。

进入android SDKtools目录下找到uiautomatorviewer.bat,双击打开这个工具,就可以使用了,如图11-45所示。


image.png

11-45  UiAutomator Viewer


案例11-4:关于坐标的API
package com.uiautomatortest;
import android.graphics.Point;
import android.os.Bundle;
import android.os.RemoteException;
import android.view.KeyEvent;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class Test extends UiAutomatorTestCase {
public void testClick(){
        //get the display height and width
        int h=UiDevice.getInstance().getDisplayHeight();
        int w=UiDevice.getInstance().getDisplayWidth();
        Point p=UiDevice.getInstance().getDisplaySizeDp();
        System.out.println("The display width is: "+w);
        System.out.println("The display height is: "+h);
        System.out.println(p);
        //click the clock
        UiDevice.getInstance().click(159,223);
       }
}


3.拖曳与滑动

1)概念介绍

  •  拖曳:将组件从一个坐标移动到另一个坐标。
  •  移动:从一个坐标点移动到另一个坐标点。
  •  步长:从一点滑动到另一点使用的时间。

2)拖曳与滑动的相关API(表11-4


11-4                                                   拖曳与滑动的相关API

返回值

方法名

描述

boolean

dragint startX,int startY,int endX,int endY,int  steps

把对象从一个坐标拖动到另一个坐标

boolean

swipePoint[] segment,int segmentSteps

在点阵列中滑动,5ms一步

boolean

swipeint startX,int startY,int endX, int endY, int  steps

通过坐标滑动屏幕

 

案例11-5:关于拖曳与滑动的API
package com.uiautomatortest;
import android.graphics.Point;
import android.os.Bundle;
import android.os.RemoteException;
import android.view.KeyEvent;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class Test extends UiAutomatorTestCase {
    public void testDragAndSwipe(){
//[64,577][128,640]
        int startX,startY,endX,endY,steps;
        startX=(128-64)/2+64;
        startY=(640-577)/2+577;
        endX=startX;
        endY=startY-200;
        steps=100;
        UiDevice.getInstance().drag(startX,startY,endX,endY,steps);
        Point p1=new Point();
        Point p2=new Point();
        Point p3=new Point();
        Point p4=new Point();
        p1.x=78;p1.y=30;
        p2.x=235;p2.y=309;
        p3.x=224;p3.y=414;
        p4.x=76;p4.y=409;
Point[] ps={p1,p2,p3,p4,p1};
        UiDevice.getInstance().swipe(ps,50);
        //(278,374),(69,373) 
        int startX=278;
        int startY=374;
        int endX=69;
        int endY=373;
        int steps=100;
        UiDevice.getInstance().swipe(startX,startY,endX,endY,steps);
    }
 }


4.屏幕旋转

1)屏幕旋转相关知识

旋转方向:0°90°(向左转)、180°270°(向右转)。

重力感应器:重力感应器是旋转所依靠的。

固定位置:指将屏幕方向固定在0°90°或者180°等。

物理旋转:物理旋转与重力感应器关联在一块,关闭物理旋转就是关闭了重力感应器,反之亦然)。

2)旋转屏幕相关API(表11-5


11-5                                                       旋转屏幕相关API

返回值

方法名

描述

void

setOrientationLeft()

通过禁用传感器,然后模拟设备向左转,并且固定位置

void

setOrientationNatural()

通过禁用传感器,然后模拟设备转到其自然默认的方向,并且固定位置

void

setOrientationRight()

通过禁用传感器,然后模拟设备向右转,并且固定位置

void

unfreezeRotation()

重新启动传感器和允许物理旋转

boolean

isNaturalOrientation()

检测设备是否处于默认旋转状态

int

getDisplayRotation()

返回当前的显示旋转,0°90°180°270°值分别为0123

void

freezeRotation()

禁用传感器和冻结装置物理旋转在其当前旋转状态

 

案例11-6:关于屏幕旋转的API
package com.UiAutomator;
import java.io.File;
import android.os.Bundle;
import android.os.RemoteException;
import android.view.KeyEvent;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class Test1 extends UiAutomatorTestCase {
public void testOrientation() throws RemoteException{
       int r=UiDevice.getInstance().getDisplayRotation();
        if(r==0){
            System.out.println("r="+r);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==1){
            UiDevice.getInstance().setOrientationNatural();
            Sleep(1000);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==2){
            UiDevice.getInstance().setOrientationNatural();
            sleep(1000);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==3){
            UiDevice.getInstance().setOrientationNatural();
        }
}
 }     int r=UiDevice.getInstance().getDisplayRotation();
        If(r==0){
            System.out.println("r="+r);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==1){
            UiDevice.getInstance().setOrientationNatural();
            Sleep(1000);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==2){
            UiDevice.getInstance().setOrientationNatural();
            Sleep(1000);
            UiDevice.getInstance().setOrientationLeft();
        }
        If(r==3){
            UiDevice.getInstance().setOrientationNatural();
        }
}
 }


5UiSelector对象

这个对象可以理解为一种条件对象,描述的是一种条件,经常配合UiObject使用,可以得到某个(某些)符合条件的控件对象。

  •  Checked(boolean val)

描述一种check状态为val的关系。

  •  className(className)

      描述一种类名为className的对象关系。

  •  clickable(boolean val)

checked类似,描述clickable状态为val的关系。

  •  description(desc)

介绍。

  •  descriptionContains(desc)

description类似。

  •  focusable(boolean val)

checked类似。

  •  indexindex)

当前对象在父对象集中的索引作为描述。

  •  packageName(Stringname)

用包名作为条件描述。

  •  selected(val)

描述一种选择关系。

  •  text(text)

最常用的一种关系,用控件上的文本即可找到当前控件。需要注意,所有使用text属性找到的控件,必须是英文的。也就是说,不支持通过中文查找控件。

  •  textContains(text)

text类似。

  •  textStartsWith(text)

text类似。


6UiObject对象

这个对象可以理解为控件的对象。一般地,UiObject对象可以通过以下形式得到:

UiObject mItem = new UiObject(new UiSelector().text("English"));

也就是配合一个UiSelector,就可以得到一个控件,具体见下面的案例分享。

  •  click()

点击控件。

  •  clickAndWaitForNewWindow()

点击某个控件,并等待窗口刷新。

  •  longClick()

长按。

  •  clearTextField()

清除文本,主要针对编辑框。

  •  getChildCount()

这个方法可以看出,其实UiObject也可以是一个控件的集合。

  • getPackageName()

得到控件的包名。

  •  getSelector()

得到当前控件的选择条件。

  •  getText()

得到控件上的Text

  •  isCheckable()
  •  isChecked()
  •  isClickable()
  •  isLongClickable()
  •  isScrollable()
  •  isScrollable()
  •  isSelected()

判断是否具备某个属性。


7UiCollection对象

这个对象可以理解为一个对象的集合。因为UiSelector描述后得到的有可能是多个满足条件的控件集合,因此可以用来生成UiCollection

UiCollection mUiCollection = new UiCollection(new UiSelector().text("Settings"));

getChild(selector);

从集合中再次通过UiSelector选择一个UiObject对象。

  •  getChildByDescription(childPattern,text)

从一个匹配模式中再次以text为条件选择UiObject

getChild(selector)

从集合中再次通过UiSelector选择一个UiObject对象

getChildByDescription(childPattern, text)

从一个匹配模式中再次以text为条件选择UiObject


8API详解

对于功能测试用例,第一步获取对象,第二步进行操作,第三步进行判断。

1)获取对象

根据笔者经验获取对象最好用的方法是:

UiSelector button=newUiSelector().resourceId("com.example.demo4:id/button1");

obj = new UiObject(button);

Obj.click();

其中com.example.demo4安卓APP的类名,button1R.java中对应元素的id名。

public static final class id {

public static final intaction_settings=0x7f08000c;

public static final int button1=0x7f080005;

另外还可以通过以下方法来定位。


案例11-7:构建一个以‘微’开头的UiSelector
UiSelector wx=new UiSelector().textStratWith(“微”) ;
UiObject obj = new UiObject(wx);
Obj.click();


案例11-8:构建一个有‘微’的UiSelector
UiSelector wx=new UiSelector().textContains(“微”) ;
UiObject obj = new UiObject(wx) ;
obj.click ();


案例11-9:构建一个class属性为android.widget.TextViewtext属性为微信的UiSelector
UiSelector wx=new UiSelector().className(“android.widget.TextView”).text(“微信”);
UiObject obj = new UiObject(wx);
obj.click();


案例11-10:构建一个聚焦的classNameandroid.widget.CheckBox聚焦的控件。
UiSelector x=new UiSelector().fousable(true).className(“android.widget.CheckBox”);
UiObject obj = new UiObject(x);
obj.click();

2)操作


案例11-11:点QQ APP
UiSelector qq=new UiSelector().text(“QQ”);
UiObject obj = new UiObject(qq);
obj.click();


案例11-12:长按QQ APP
UiSelector qq=new UiSelector().text(“QQ”);
UiObject obj = new UiObject(qq);
obj.longClick();


案例11-13:把QQ移动到【560,600】坐标处,40step
UiSelector qq=new UiSelector().text(“QQ”);
UiObject obj = new UiObject(qq);
obj.dragTo(560,600,40);


案例11-14:交换QQ与计算器的位置。
UiSelector qq=new UiSelector().text(“QQ”);
UiObject obj = new UiObject(qq);
UiSelector calc=new UiSelector().text(“计算器”);
UiObject obj1 = new UiObject(calc);
obj.drapTo(obj1,40);


案例11-15:按第3APP向左划屏。

因为instance的编号从0开始,所以这里为2

UiSelector View=new UiSelector().className(“android.view.View”).instance(2);
UiObject obj = new UiObject(View);
obj.SwipeLeft(10);


案例11-16:模拟短信输入。
UiSelector edit=new UiSelector().className(“android.view.EditText”).instance(0);
UiObject obj = new UiObject(edit);
obj.setText(“13681732596”);
UiSelector edit1=new UiSelector().className(“android.view.EditText”).instance(1);
UiObject obj1 = new UiObject(edit1);
obj1.setText(“hi”);
obj1.clearTextField();  //重新输入
obj1.setText(“hello”);


案例11-17:获得屏幕下方的文本信息。
UiSelector View=new UiSelector().className(“android.view.View”).instance(4);
UiObject obj = new UiObject(View);
int count = obj.getChildCount();
for(int j=0;j<count;j++){
     UiObject child = obj.getChild(new UiSelector().index(j));
    System.out.println(child.getText());
}


案例11-18:判断对象是否存在。
UiSelector View=new UiSelector().className(“android.view.View”).instance(2);
UiObject obj = new UiObject(View);
If (obj.exists ())
{ 
    System.out.println(“Object exists!”);
}else{
     System.out.println(“Object is not exist!”);
}

当然可以用assertEqualsassertTrueassertFalseassertNullassertNotNullassertSameassertNotSame,参见本篇第8.1.5节介绍。


顾翔凡言:

不是好的工作会给你带来好的心情,而是好的心情会给你带来好的工作。

目录
相关文章
|
存储 敏捷开发 编解码
《软件测试技术实战 设计、工具及管理》联载-11
《软件测试技术实战 设计、工具及管理》联载-11
108 0
《软件测试技术实战 设计、工具及管理》联载-11
|
缓存 网络协议 关系型数据库
《软件测试技术实战 设计、工具及管理》联载-22
《软件测试技术实战 设计、工具及管理》联载-22
109 0
《软件测试技术实战 设计、工具及管理》联载-22
|
SQL 前端开发 关系型数据库
《软件测试技术实战 设计、工具及管理》联载-4
《软件测试技术实战 设计、工具及管理》联载-4
65 0
《软件测试技术实战 设计、工具及管理》联载-4
|
测试技术
《软件测试技术实战 设计、工具及管理》联载-10
《软件测试技术实战 设计、工具及管理》联载-10
98 0
《软件测试技术实战 设计、工具及管理》联载-10
|
测试技术
软件测试技术实战 设计、工具及管理》联载-56
软件测试技术实战 设计、工具及管理》联载-56
63 0
软件测试技术实战 设计、工具及管理》联载-56
|
测试技术 BI 数据库
《软件测试技术实战 设计、工具及管理》联载-45
《软件测试技术实战 设计、工具及管理》联载-45
95 0
《软件测试技术实战 设计、工具及管理》联载-45
|
监控 Java 测试技术
《软件测试技术实战 设计、工具及管理》联载-40
《软件测试技术实战 设计、工具及管理》联载-40
103 0
《软件测试技术实战 设计、工具及管理》联载-40
|
SQL 编解码 前端开发
《软件测试技术实战 设计、工具及管理》联载-5
《软件测试技术实战 设计、工具及管理》联载-5
154 0
《软件测试技术实战 设计、工具及管理》联载-5
|
敏捷开发 Web App开发 算法
《软件测试技术实战 设计、工具及管理》联载-41
《软件测试技术实战 设计、工具及管理》联载-41
116 0
《软件测试技术实战 设计、工具及管理》联载-41
|
开发框架 IDE 算法
《软件测试技术实战 设计、工具及管理》联载-39
《软件测试技术实战 设计、工具及管理》联载-39
127 0
《软件测试技术实战 设计、工具及管理》联载-39