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

相关推荐
李堇2 小时前
android滚动列表VerticalRollingTextView
android·java
lxysbly3 小时前
n64模拟器安卓版带金手指2026
android
游戏开发爱好者86 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码20356 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥6 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓7 小时前
[JDBC]元数据
android
独行soc7 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能7 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿7 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市
独行soc7 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮