Android自动化测试四 UiAutomator用法

它是一个Android自动化测试框架,是谷歌在Android4.1版本发布时推出的一款用Java编写的UI测试框架。它只能用于UI也就是黑盒方面的测试。所以UiAutomator只能运行在4.1以后的版本中。其最大的特点就是可以跨进程操作,我们可以使用uiautomator框架提供的一些方便的API来对安卓应用进行一系列的自动化测试操作,如点击、滑动、键盘输入、长按以及常用的断言方法等。可以替代以前繁琐的手工测试。

下面总结一下该框架的几个优点:

  1. Google自家推出的,其稳定性和后续的维护更新可以得到保障,运行时也有更多的权限。
  2. 可以跨进程操作,这点比起其它基于instrumentation框架的自动化工具如Robotium是无法直接做到的。
  3. 运行速度快。
    缺点:
  4. 不支持Android4.1以下的版本。
  5. 不支持Webview,所以一般无法对浏览器应用进行测试。
UiAutomator 框架原理分析:

首先,UiAutomator是Google参考微软的UiAutomation提供的一套用在Android上的自动化测试框架。基于Android AccessilibilityService提供。那么至于什么是AccessilibilityService,在这里简单介绍下:Android AccessilibilityService,是一个可访问服务,它是一个为增强用户界面并帮助残疾用户的应用程序,或者用户可能无法完全与设备的交互。举个简单的例子,假如一个用户在开车。那么用户就有可能需要添加额外的或者替代的用户反馈方式。其应用方式一般有两种:

第一种方法是:UiAutomatorView + monkey。它与hierachyview + monkey差不多。其区别是:UiAutomatorView通过ADB向设备侧发送一个dump命令,而不是建立一个socket,下载一个包含当前界面控件布局信息的xml文件。相比较hierachyview下载的内容而言,该文件小很多。因此,从效率上讲,这种方法比第一种应用模式快很多。

第二种方法是: 直接调用UiAutomator框架对外提供的API,主要有UiDevice、UiSelector、UiObject和 UiScrollable等。其原理与第一种方式即HierachyView + Monkey差不多。其过程大致是:首先,UiAutomator测试框架通过Accessibilityservice,获取当前窗口的控件层次关系及属性信息,并查找到目标控件。若是点击事件,则计算出该控件的中心点坐标。其次,UiAutomator通过 InputManager.getInstance().injectInputEvent隐藏接口来注入用户事件(点击、输入类操作),从而实现跨进程自动化的目的。

UiAutomatorTestCase :这个类是继承自Junit TestCase (Junit),对外提供setup、teardown等,以便初始化用例、清除环境等。所以我们在编写的UiAutomator 的脚本时一般都要继承这个类,这样就可以直接使用它的一些方法和Junit单元测试框架中的Assert断言机制。

UIAutomator2.0

We're pleased to announce the release of UIAutomator 2.0! This version is a significant update from the previous release. Most importantly, UI Automator is now based on Android Instrumentation and you can build and run tests with the './gradlew connectedCheck' command.

UiAutomator2.0的jar包并不是在以前SDK/platforms/android-19/下。现在我们要这么做

  1. 通过Android SDK Manager中的 Android Support Repository 项进行安装

  2. 下载下来的jar包的路径为/extras/android/m2repository

  3. 新建一个android项目,编写一个简单的应用

  4. 在build.gradle中配置依赖项:

    dependencies {
    androidTestCompile 'com.android.support.test:runner:0.3'
    // Set this dependency to use JUnit 4 rules
    androidTestCompile 'com.android.support.test:rules:0.3'
    // Set this dependency to build and run Espresso tests
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
    // Set this dependency to build and run UI Automator tests
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
    }

  5. 设置AndroidJunitRunner为默认的testInstrumentationRunner

    android {
    defaultConfig {
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    }

  6. 编写测试代码,在androidTest目录下面新建测试类

    public class LoginTest extends InstrumentationTestCase {

    复制代码
     protected UiDevice device = null;
     protected String appName = "magicCard";
    
     public void runApp(String appName) throws UiObjectNotFoundException, RemoteException {
         device = UiDevice.getInstance(getInstrumentation());
         device.pressHome();
         device.waitForWindowUpdate("", 2000);
    
         UiObject2 allAppsButton = device.findObject(By.desc("Apps"));
         allAppsButton.click();
         device.waitForWindowUpdate("", 2000);
    
         UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true));
         appViews.setAsHorizontalList();
    
         UiObject settingsApp = appViews.getChildByText(new UiSelector().className(TextView.class.getName()), appName);
         settingsApp.clickAndWaitForNewWindow();
    
         assertTrue("Unable to detect app", settingsApp != null);
     }
    
     @Override
     public void setUp() throws RemoteException, UiObjectNotFoundException {
         this.runApp(appName);
     }
    
     @Override
     public void tearDown() throws RemoteException, UiObjectNotFoundException {
         //Empty for the moment
     }
    
     public void testUS1() {
         UiObject2 usernameLabel = device.findObject(By.clazz(TextView.class.getName()).text("Username"));
         assertTrue("Username label not found", usernameLabel != null);
     }

    }

基于Instrument的方便一点就是不需要remote debug的方式进行调试。并且做参数化之类的也方便了很多。

2.0不用再继承UiAutomatorTestCase,但却需要继承InstrumentationTestCase。

获取设备的方式也变化了,UiDevice.getInstance(getInstrumentation()) 这才是正确的使用方法。之前常用的两种方式都不再可行。

可以通过如下的adb命令调用

复制代码
adb shell am instrument -w -r   -e debug false -e class com.cxq.uiautomatordemo.UiTest com.cxq.uiautomatordemo.test/android.test.InstrumentationTestRunner

在dependencies中用到了compile、testCompile、androidTestCompile三种依赖方式,让我们来看看他们有什么区别:

compile:参与编译,并且会打包到debug/release apk中。

testCompile:只参与单元测试编译,不会打包到debug/release apk包中,不需要设备支持。

androidTestCompile:只参与UI测试编译,不会打包到debug/release apk包中,需要设备支持。

除此之外还有Provided、APK、Debug compile和Release compile:

Provided:只参与编译,不会打包到debug/release apk中。

APK:不参与编译,只会打包到debug/release apk中。

Debug compile:只参与debug编译,只会打包到debug apk中。

Release compile:只参与release编译,只会打包到release apk中。

UIAutomator1.0
  1. 新建Java工程

  2. 导入lib包 android.jar 和 uiautomator.jar ,选中点击右键Add to buildPath

  3. 新建测试类demo

    public class Demo extends UiAutomatorTestCase{}

  4. 写测试方法A,B,C(testcase)

  5. 编译运行:
    5.1. <android-sdk>/tools/android create uitest-project -n <name> -t 1 -p <path>
    说明一下各个参数的作用,如果已经将android sdk的路径配置到了系统的path中,输入命令"android create uitest-project"就可以查看到相应的帮助

  • -n --name : Project name. 就是在eclipse中创建的项目的名字。
  • -t --target : Target ID of the new project. [required] 这个id是本机上android targets的id,可以通过命令 "android list"来查询,得到结果,选择android-17以上版本前面所对应的id,运行完成后,工作空间下生成文件build.xml

5.2. 修改build.xml 将help改为build

复制代码
<?xml version="1.0" encoding="UTF-8"?>            
<project name="demo1" default="build">        

5.3.在build.xml上点击右键,选择"Run As" -> "Ant Build",编译成功,在工作空间bin下生成一个jar包demo.jar

5.4. adb push demo.jar /data/local/tmp/

5.5. adb shell uiautomator runtest demo.jar -c A -c B -c C (可指定多个testcase,不指定则运行所有)

uiautomator的help帮助:

支持三个子命令:rutest/dump/events

  • runtest命令-c指定要测试的class文件,用逗号分开,没有指定的话默认执行测试脚本jar包的所有测试类.注意用户可以以格式 c l a s s / class/ class/method来指定只是测试该class的某一个指定的方法
  • runtest命令-e参数可以指定是否开启debug模式
  • runtest命令-e参数可以指定test runner,不指定就使用系统默认。我自己从来没有指定过
  • runtest命令-e参数还可以通过键值对来指定传递给测试类的参数

UiAutomator2改进

  1. 基于 Instrumentation,可以获取应用Context,使用 Android服务及接口

  2. 基于 Junit4,测试用例无需继承于任何父类,方法名不限,使用注解 Annotation进行

  3. UI执行效率比 1.0 快,测试执行可使用AndroidJunit 方式及gradle 方式

  4. API 更新,新增UiObject2、Until、By、BySelector等:APIFor UI Automator

  5. Log 输出变更,以往使用System.out.print输出流回显至执行端,2.0 输出至Logcat

AndroidJUnitRunner
AndroidJUnitRunner
InstrumentationTestRunner
Fundamentals of Testing
UI Automator
androidx.test
Test UI for multiple apps
Instrumentation

相关推荐
ŧ榕树先生1 小时前
稳定的Android studio版本安装教程
android·ide·android studio
早上好啊! 树哥2 小时前
常见的文件加密方式之【异或加密】,代入原理看例子,帮助更好的理解。
android·java·junit
沅霖3 小时前
Android: Handler 的用法详解
android
鸿蒙布道师3 小时前
鸿蒙NEXT开发数值工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
Yang-Never5 小时前
Open GL ES ->GLSurfaceView在正交投影下的图片旋转、缩放、位移
android·开发语言·kotlin·android studio·贴图
粤M温同学5 小时前
使用Android 原生LocationManager获取经纬度
android
stevenzqzq5 小时前
Android Hilt 教程
android
CYRUS_STUDIO5 小时前
Frida Stalker Trace 指令跟踪&寄存器变化监控
android·逆向·汇编语言
bst@微胖子5 小时前
Flutter之设计与主题&字体
android·flutter
深圳之光7 小时前
增加android 禁用相机后摄的接口
android·数码相机