快速玩转UIautomator2

简述:

Uiautomator2
GoogleSample

UIautomator2 是Google官方针对Android平台推出的一个基于UI自动化测试的框架;适用于跨系统和已安装应用程序的跨应用程序功能UI测试;无需设备root、无需重签名apk、无需配置deviceName、Android 版本等

此处不再过多介绍客户端各种UI自动化框架(Appium、roubotium等)的对比,没有最好用的框架,只有最合适的框架!

UiAutomator2新特性:
  • 可获取应用Context对象,通过context可使用Android相关服务于接口(如:获取app信息、wifimanager、操作Activity等)
  • 基于Junit4,可直接通过注解方法使用 @RunWith(AndroidJUnit4.class)
  • API优化,新增UiObject2、Until、By、BySelector等

循序渐进式:

元素查找:
  • 通过Android sdk/tools/uiautomatorviewer.bat 来查找元素位置、层级、属性
元素事件:
  • click() 点击
  • longClick() 长按
  • drag() 拖拽
  • swipe() 滑动
  • setText() 输入
元素属性:
  • id
  • className
  • textName
  • 坐标 (适用于特殊场景:如 widget)
常用类:
  • UiDevice 获取设备实例
  • UiObject2 获取元素对象
  • UiScrollable 处理滚动事件的类
调用封装方法demo
	/**
	 * 调用 baseutil的  getListItem()
	 * 遍历ListView中的每一个Item,并点击打开对应item,等到新界面出现
	 */
    private void checkSettingLayout(int index){
        for (int i=0;i<4;i++){
            getListItem(LIST_VIEW_NAME,2).get(index).clickAndWait(Until.newWindow(),20000);
            getListItem(LIST_VIEW_NAME,2).get(i).clickAndWait(Until.newWindow(),20000);
        }
    }
    
    /**
	 * 调用 baseutil的  getElement()
	 * 调用 baseutil 的 isWifi()
	 * 用户反馈界面,输入反馈内容,并提交
	 */
	 
    private void checkFeedbackSubmit(){
        String descript = "com.test.launcher:id/et_question_descript";
        String submit = "com.test.launcher:id/feedback_title_submit";
        String etType = "This is a test..." + '\n' + "qwertyuiop+QWERTYUIOP+1234567890+!@#$%^&* + EditText属性 -->输入类型测试" ;
        mObject2 = getElement(descript,1);
        mObject2.setText(etType);
        sleep(2000);
        if (!isWifi()){ //wifi未连接
            getElement(submit,1).clickAndWait(Until.newWindow(),3000);
            Log.i(TAG,"wifi 未连接");
        }else {
            Log.i(TAG,"wifi 已连接");
            //EditText check setText submit
            getElement(submit,1).clickAndWait(Until.newWindow(),20000);
            sleep(2000);
            onClickSetListItem(4);
        }
    }
常用方法封装
package com.hankhe.autotest.baseutil;

import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.util.Log;

import org.junit.Assert;

import java.util.List;

/**
 * author: Hank
 * create: 2018/5/1
 * description: BaseEvent 二次封装uiautomator2   增加代码复用性 Android 4.4+
 */

public class BaseEvent{
    private static final String TAG = "Hank";
    public UiObject2 uiObject2;
    public UiDevice uiDevice;
    public Instrumentation instrumentation;
    private UiScrollable uiScrollable;
    private UiObject uiObject;
    private int width,height;

    public BaseEvent(){
        instrumentation = InstrumentationRegistry.getInstrumentation();
        uiDevice = UiDevice.getInstance(instrumentation);

        width = uiDevice.getDisplayWidth();
        height = uiDevice.getDisplayHeight();
    }

    public void longClick(String str){
        uiObject2 = uiDevice.findObject(By.clazz(str));
        uiObject2.longClick();
        sleep(2000);
    }
    //Desktop bottomMenu 中心点
    public void longTouch(){
        uiDevice.swipe(width/2,height/2,width/2,height/2,100);
    }
    /**
     * 向右滑动
     * @param step 步长/速度
     * **/
    public void swipToRight(int step){
        uiDevice.swipe(width/4,height/2,width*3/4,height/2,step);
    }
    /**
     * 向左滑动
     * @param step 步长/速度
     * **/
    public void swipLeft(int step){
        uiDevice.swipe(width*3/4,height/2,width/4,height/2,step);
    }
    /**
     * 获取目标元素  + 不加断言(适用于if操作场景 null/equals)
     * @param str  元素属性
     * @param type 1:byID    2:byClassname  3:byText
     */
    public UiObject2 getElement(String str,int type){
        UiObject2 uiObject2 = null;
        switch (type){
            case 1:
                uiObject2 = uiDevice.findObject(By.res(str));
                break;
            case 2:
                uiObject2 = uiDevice.findObject(By.clazz(str));
                break;
            case 3:
                uiObject2 = uiDevice.findObject(By.text(str));
                break;
            default:
                break;
        }
        return uiObject2;
    }
    /**
     * 点击目标元素 + clickAndWait + 断言
     * @param str  元素属性
     * @param type 1:byID    2:byClassname
     */
    public void elementClick(String str,int type){
        switch (type){
            case 1:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.res(str)),20000));
                uiObject2 = uiDevice.findObject(By.res(str));
                break;
            case 2:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(str)),20000));
                uiObject2 = uiDevice.findObject(By.clazz(str));
                break;
            case 3:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.text(str)),20000));
                uiObject2 = uiDevice.findObject(By.text(str));
                break;
            default:
                break;
        }
        uiObject2.clickAndWait(Until.newWindow(),3000);//Tiemout 5000
    }
    /**
     * 获取直接子元素 + 断言  (针对Android控件:listview、ScrollView、receclyView、gidView)
     * @param str  元素属性
     * @param type 元素定位Type   1:byID    2:byClassName
     */
    public List<UiObject2> getListItem(String str,int type){
        List<UiObject2> listItem = null;
        switch (type){
            case 1:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.res(str)),20000));
                uiObject2 = uiDevice.findObject(By.res(str));
                listItem = uiObject2.getChildren();
                break;
            case 2:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(str)),20000));
                uiObject2 = uiDevice.findObject(By.clazz(str));
                listItem = uiObject2.getChildren();
                break;
            default:
                break;
        }
        return listItem;
    }
    /**
     * 获取所有子元素 + 断言  (针对Android控件:listview)
     * @param parents  父元素属性
     * @param child  子元素(目标元素)
     * @param type 元素定位Type  1:byID    2:byClassName
     */
    public List<UiObject2> getListAllItem(String parents,String child,int type){
        List<UiObject2> allItem = null;
        switch (type){
            case 1:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.res(parents)),20000));
                uiObject2 = uiDevice.findObject(By.res(parents));
                allItem = uiObject2.findObjects(By.res(child));
                break;
            case 2:
                Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(parents)),20000));
                uiObject2 = uiDevice.findObject(By.clazz(parents));
                allItem = uiObject2.findObjects(By.clazz(child));
                break;
            default:
                break;
        }
        return allItem;
    }
    /**
     * UiObject
     * 获取指定子元素  + 断言  --- Scroll不滚动查询 ,屏幕所展示的非隐藏的  (针对Android控件:ScrollView)
     * 针对 没有text/id的 列表元素
     * @param parentName  父元素属性
     * @param childName  子元素(目标元素)
     * @param index 元素
     */
    public UiObject getScrollDisableItem(String parentName,String childName,int index){
        Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(parentName)),20000));
        uiScrollable = new UiScrollable(new UiSelector().className(parentName));

        try {
            uiObject = uiScrollable.getChildByInstance(new UiSelector().className(childName),index);
        } catch (UiObjectNotFoundException e) {
            e.printStackTrace();
        }
        return  uiObject;
    }
    /**
     * UiObject
     * Scroll滚动查询子元素  + 断言    (针对Android控件:ScrollView)
     * @param parentName  父元素属性
     * @param childName  子元素(目标元素)
     * @param textName 元素text
     * @param scroll  是否滚动查询  true:滚动   false:不滚动
     */
    public UiObject getScrollEableItem(String parentName,String childName,String textName,boolean scroll){
        Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(parentName)),20000));
        uiScrollable = new UiScrollable(new UiSelector().className(parentName));

        try {
            uiObject = uiScrollable.getChildByText(new UiSelector().className(childName),textName,scroll);
        } catch (UiObjectNotFoundException e) {
            e.printStackTrace();
        }
        return  uiObject;
    }
    /**
     * Scroll 快速滑动  + 断言    (针对Android控件:ScrollView)
     * @param parentName  父元素属性
     */
    public UiScrollable swipflingScroll(String parentName){
        Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(parentName)),20000));
        uiScrollable = new UiScrollable(new UiSelector().className(parentName));
        return uiScrollable;
    }
    /**
     * Scroll 滚动  + 断言    (针对Android控件:ScrollView)
     * @param parentName  父元素属性
     */
    public UiScrollable swipScroll(String parentName){
        Assert.assertTrue(uiDevice.wait(Until.hasObject(By.clazz(parentName)),20000));
        uiScrollable = new UiScrollable(new UiSelector().className(parentName));
        uiScrollable.setSwipeDeadZonePercentage(0.1);//不滑动区域百分比
        return uiScrollable;
    }
    /**
     * 判断wifi是否开启
     * <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     */
    public boolean isWifi() {
        Context mContext=InstrumentationRegistry.getInstrumentation().getContext();
        boolean state = false;
        ConnectivityManager mcM= (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        if(mcM.getActiveNetworkInfo() != null){
            state = mcM.getActiveNetworkInfo().isAvailable();
        }
        return state;
    }
    /**
     * 检测是否有permission Dialog,并执行选择 Allow/Deny
     * @param status  1:Allow   2:Deny
     * **/
    public void checkPermissionMsg(int status){
        String sourceId = "com.android.packageinstaller:id/permission_message";
        String sourceAllowBtn = "com.android.packageinstaller:id/permission_allow_button";
        String sourceDenyBtn = "com.android.packageinstaller:id/permission_deny_button";
        uiObject2 = uiDevice.findObject(By.res(sourceId));
        if (uiObject2 != null){
            switch (status){
                case 1:
                    uiObject2 = uiDevice.findObject(By.res(sourceAllowBtn));
                    uiObject2.clickAndWait(Until.newWindow(),30000);
                    Log.i(TAG,"Permission Dialog ---> Allow " );
                    break;
                case 2:
                    uiObject2 = uiDevice.findObject(By.res(sourceDenyBtn));
                    uiObject2.clickAndWait(Until.newWindow(),30000);
                    Log.i(TAG,"Permission Dialog ---> Deny ");
                    break;
                default:
                    break;
            }
        }else {
            Log.i(TAG,"NO Permission Dialog");
        }
    }

    /**
     * 启动指定APP
     * @param packageName
     * **/
    public void doStartApp(String packageName){
        Context context=InstrumentationRegistry.getInstrumentation().getContext();
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }
    /**
     * 启动 所有已安装 APP
     * **/
    public void doStartAppAll(){
        Context context=InstrumentationRegistry.getContext();

        PackageManager pm=context.getPackageManager();
        List<PackageInfo> packageInfo=pm.getInstalledPackages(0);
        List<ApplicationInfo> applicationInfos=pm.getInstalledApplications(0);

        Intent mainIntent=new Intent(Intent.ACTION_MAIN,null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        List<ResolveInfo> resolveInfos=pm.queryIntentActivities(mainIntent,0);

        for(ResolveInfo reinfo:resolveInfos){
            String activityName=reinfo.activityInfo.name;
            String pkgName=reinfo.activityInfo.packageName;

            Intent launchIntent=new Intent();
            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            launchIntent.setComponent(new ComponentName(pkgName, activityName));
            context.startActivity(launchIntent);
            Log.d("启动App",pkgName);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //关闭app 把Activity从栈中移除
            uiDevice.pressBack();
            uiDevice.pressBack();
            uiDevice.pressBack();
            uiDevice.pressBack();
        }

    }
    /**
     *  睡眠
     * @param sleep  单位:ms
     * **/
    public void sleep(int sleep){
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_27032161/article/details/89542656