美文网首页Android葵花宝典Android进阶ITBOX
Android自动化测试工具 UiAutomator使用详解

Android自动化测试工具 UiAutomator使用详解

作者: 容华谢后 | 来源:发表于2017-08-16 07:19 被阅读2792次
    封面

    本文测试用例下载地址

    1.介绍

    Android团队在4.1版本(API 16)中推出了一款全新的UI自动化测试工具UiAutomator,用来帮助开发人员更有效率的完成App的Debug工作,同时对于测试人员也是一大福音,为什么这么说呢?

    举个栗子

    测试:“我发现了一个bug,你写的App打开A页面,再打开B页面有时会出现闪屏问题。”

    开发:“嗯?还有这样的问题,复现给我看看。(内心独白:我写的App怎么会有bug,一定是你用的姿势不对)”

    测试:一段忙碌的操作之后...“咦,怎么不出现了?”

    开发:“那你先回去吧,复现再告诉我。”

    几天过去了...

    测试:满心欢喜状,“上次那个问题我复现了,操作给你看....我去,怎么又不出现了!”

    开发:“是不是设备有问题,你换个设备再试试呢?”

    测试:“宝宝心里苦,但是宝宝不说!”

    有了UiAutomator之后:

    测试:“我发现了一个bug,你写的App打开A页面,再打开B页面有时会出现闪屏问题。”

    开发:“这个简单,我用UiAutomator写个测试用例,分分钟解决。”

    测试:“厉害了Word哥!”

    全剧终!

    UiAutomator提供了以下两种工具来支持UI自动化测试:

    • uiautomatorviewer:用来分析UI控件的图形界面工具,位于SDK目录下的tools文件夹中。

    • uiautomator:一个java库,提供执行自动化测试的各种API。

    2.环境搭建

    本文使用了Android Studio作为IDE,Eclipse,Please go home!

    Eclipse go home

    首先在app根目录的build.gradle文件中加入依赖:

    // AS默认配置,如果如果没有记得加上
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
    

    注意:uiautomator库支持的最低版本为API 18,所以本篇文章开发环境的minSdkVersion为18。

    配置testInstrumentationRunner为AndroidJunitRunner:

    defaultConfig {
        ...
        // 这个AS会为我们默认配置,如果没有记得加上
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    

    看下完整的build.gradle文件:

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.3"
        defaultConfig {
            applicationId "com.yl.uiautomatordemo"
            minSdkVersion 18
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:25.3.1'
        testCompile 'junit:junit:4.12'
        androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
    }
    

    在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中。

    3.测试流程

    • 1.安装被测试App到手机中。

    • 2.打开UI分析工具uiautomatorviewer.bat,分析当前UI的界面元素,确保App的各个控件可以被测试工具获取到。

    • 3.根据App使用流程编写测试用例。

    • 4.运行测试用例进行测试,定位bug,解决bug。

    4.实践

    《可折叠的Toolbar—CollapsingToolbarLayout》中的Demo为例,假设反复滑动布局会导致应用crash,针对这种情况,我们来写一个测试用例:

    分析UI的界面元素

    启动被测试App,打开uiautomatorviewer.bat工具,点击左上角的Device Screenshot按钮捕获屏幕快照,如下图所示,左侧显示屏幕快照,右侧显示布局结构与控件属性,控件属性在编写测试用例时会用到。

    分析UI的界面元素

    编写测试用例

    选择File—New—New Project新建项目,和创建普通项目的流程相同,只不过不需要创建Activity,创建完成后,项目结构如下图所示:

    项目结构

    可以看到,在app—src目录下,AS为我们自动创建了一个androidTest文件夹,用来编写UI测试用例,同级还有一个test文件夹,用来编写单元测试用例。

    项目创建成功后,参考上文引入依赖,构建完成后,开始写测试用例吧!等等,先别急,在此之前先普及一下uiautomator的常用API:

    • UiDevice:

      设备对象,通过UiDevice的getInstance(instrumentation)方法获取,可以通过UiDevice实例来检测设备的各种属性,比如获取屏幕的方向、尺寸等,还可以通过UiDevice实例来执行设备级别的操作,比如点击Home键、返回键等:

      // 点击Home键
      uiDevice.pressHome();
      
      // 点击返回键
      uiDevice.pressBack();
      
      ...
      
    • UiSelector

      用于获取某些符合条件的UI控件对象,可以通过资源id、描述等熟悉获取:

      // 通过资源id获取
      new UiSelector().resourceId("com.yang.designsupportdemo:id/CollapsingToolbarLayout");
      
      // 通过描述文件获取
      new UiSelector().description("Navigate up")
      
      // 通过className获取
      new UiSelector().className("android.support.v7.widget.RecyclerView")
      
      ...
      
    • UiObject

      代表一个UI控件,通过uiDevice的findObject(UiSelector)方法获取,获取到UiObject实例后,就可以对UI控件进行相关的操作,比如点击、长按等:

      // 点击应用返回按钮
      UiObject back = uiDevice.findObject(new UiSelector().description("Navigate up"));
      back.click();
      
    • UiCollection

      代表UI控件集合,相当于ViewGroup,比如界面中有多个CheckBox时,可以通过类名获取到当前界面下的所有CheckBox,然后通过控件id获取指定的CheckBox对象:

      // 获取指定的CheckBox对象
      UiCollection uiCollection = new UiCollection(new UiSelector().className("类名"));
      UiObject checkBox = uiCollection.getChild(new UiSelector().resourceId(""));
      
    • UiScrollable

      代表可滚动的控件,比如打开设置的关于手机选项:

      // 滑动列表到最后,点击About phone选项
      UiScrollable settings = new UiScrollable(new UiSelector().className("android.support.v7.widget.RecyclerView"));
      UiObject about = settings.getChildByText(new UiSelector().className("android.widget.LinearLayout"), "About phone");
      about.click();
      

    看下滚动效果:

    打开关于手机

    OK,常用API到这里就说的差不多了,开始写测试用例吧!

    Talk is cheap, Show me the code.

    public class UiTest extends TestCase {
    
        public void testA() throws UiObjectNotFoundException {
            // 获取设备对象
            Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
            UiDevice uiDevice = UiDevice.getInstance(instrumentation);
            // 获取上下文
            Context context = instrumentation.getContext();
    
            // 启动测试App
            Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.yang.designsupportdemo");
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            context.startActivity(intent);
    
            // 打开CollapsingToolbarLayout
            String resourceId = "com.yang.designsupportdemo:id/CollapsingToolbarLayout";
            UiObject collapsingToolbarLayout = uiDevice.findObject(new UiSelector().resourceId(resourceId));
            collapsingToolbarLayout.click();
    
            for (int i = 0; i < 5; i++) {
                // 向上移动
                uiDevice.swipe(uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight(),
                        uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight() / 2, 10);
    
                // 向下移动
                uiDevice.swipe(uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight() / 2,
                        uiDevice.getDisplayHeight() / 2, uiDevice.getDisplayHeight(), 10);
            }
    
            // 点击应用返回按钮
            UiObject back = uiDevice.findObject(new UiSelector().description("Navigate up"));
            back.click();
    
            // 点击设备返回按钮
            uiDevice.pressBack();
        }
    }
    

    代码中写了很全的注释,简单说下,首先获取设备对象和上下文,这个后面要用到,然后启动测试App,打开需要测试的界面,上下滑动5次后退出App,由于上文中对API已经有了一定了解,看起代码来还是很轻松的。

    注意:测试方法需要以test开头,如果存在多个测试方法,以test后的字母顺序执行。

    代码写完了,接下来就要开始测试了,右击测试类选择Run按钮,或者点击测试类中的执行按钮进行测试,上面的按钮代表执行所有测试方法,下面的按钮代表只执行当前测试方法:

    执行测试

    测试执行后,可以看到控制台上打印了一些信息:

    测试信息

    可以看到,首先通过adb shell命令在设备中安装了UiAutomatorDemo和com.yl.uiautomatordemo.test两个apk,然后启动测试,此时被测App已经开始执行测试流程,执行完成后,显示测试结果,看下App的执行效果:

    UI测试

    OK,到这里,UiAutomator的基本用法就讲完了。

    5.写在最后

    源码已托管到GitHub上,欢迎Fork,觉得还不错就Start一下吧!

    GitHub传送门

    欢迎同学们吐槽评论,如果你觉得本篇博客对你有用,那么就留个言或者点下喜欢吧(^-^)

    相关文章

      网友评论

      • b127b61970ba:大佬 点击 的 方法 是 在 那个里面 的 click的 我想找到 双击的 我硬是没找到 现在 很烦 哭泣中
        b127b61970ba:@容华谢后 谢谢😜
        容华谢后:别哭,写个for循环,click两次怎么样
      • 532c79b692db:你好,你知道例如找到关机文本后找到关机的图标吗?
        容华谢后:@Ms李_c7e9 因为每种设备的关机方式都不同,可以跳转到关机的界面,然后打开uiautomatorviewer工具看下关机按钮的id或者其他属性是什么,找到之后,调用点击事件就可以了。
        532c79b692db:@容华谢后 恩恩,对
        容华谢后:找到关机的图标吗?
      • 79ce1b9ac925:非常感谢你的分享。想问一下 uiautomator 和 monkey 的区别。monkey 可以产生随机事件,相当于随机测试用例。uiautomator 是一个写测试用例的框架,用例做什么需要程序员去写,而不能自动产生。这样说对吗?
        容华谢后: @狍子先生 因为测试用例是根据具体App的id和控件属性编写的,不能自动生成。
        79ce1b9ac925:@容华谢后 谢谢你的回复。想问一下有没有自动产生测试用例的工具或者框架呢?谢谢你!
        容华谢后:对的,uiautomator是需要写测试用例的。
      • 4341d723c7bf:真机运行 java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission 是不是真机需要root啊,只能虚拟器跑啊
        容华谢后:@翅膀少了羽毛 用模拟器没问题吗,换个设备试试呢,运行的测试用例是文章里的Demo吗?
        4341d723c7bf:@容华谢后 加了还是一样的错误提示
        容华谢后:真机不需要root,可以看下是不是控件被挡住了导致的,或者添加这个权限试试<uses-permission android:name="android.permission.INJECT_EVENTS"/>
      • 4d3bf4cac28c:Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.yang.designsupportdemo");
        果断返回了一个null
        4d3bf4cac28c:@容华谢后 问题解决了,我在gradle里面修改了applicationId,测试的时候忘了这个事了:joy:
        容华谢后:安装DesignSupportDemo这个App了吗?
      • JaedenKil:你的排版做的实在太好了!
        容华谢后: @JaedenKil 哈哈哈哈,谢谢!
      • aa15d4926dc6:大神:+1::+1::+1:
        容华谢后:谢谢,大神不敢当

      本文标题:Android自动化测试工具 UiAutomator使用详解

      本文链接:https://www.haomeiwen.com/subject/pqpvrxtx.html