2

到目前为止,我们已经完成了对Espresso的介绍。从之前的文章我们可以看到,Espresso对Android APP的自动化测试提供了一系列非常强大的工具和方法。

现在试想这样一个场景:我们在APP中有一个更改头像的功能,此时我们需要调用系统相机进行拍照,然后再回到APP提交拍好的照片。在这种场景下,我们需要从自己的APP跳转到其他的APP,而这种跳转的交互在产品中是经常会发生的。

Espresso并没有对这种跨APP的交互测试提供支持。我们无法在脚本中通过Espresso获取到非自己APP之外其他APP(或者系统界面)的UI组件。这时,我们就需要用到Android提供的UI Automator来进行自动化测试。

配置

想要使用UI Automator,只需要添加如下依赖:

dependencies {
    ...
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
}

UI Automator仅支持Android 4.3(API Level 18)及以上版本。

可行性探索

在使用UI Automator编写测试脚本之前,我们需要对当前测试用例是否可以用UI Automator进行测试做一些探索。简单来说,就是要确保我们需要的界面元素是否都能找到、希望出发的操作是否都支持。

确定可行性的方法也很简单,只要确保我们需要操作的UI元素有可以进行匹配的属性(这一点类似于Espresso),比如唯一的ID,text等等。我们可以按照该系列第四篇对uiautomatorviewer的介绍来使用Android提供的uiautomatorviewer工具,对测试用例中的各个页面,尤其是跨APP交互的页面中的各个UI元素进行分析,确保每个我们需要操作的元素都有相应可以匹配的属性值,以便于我们可以通过脚本找到相应的元素。

对此,Android官方对我们开发者也提出了一些针对自动化测试的建议,便于我们在开发时采用:

  • 对于ImageView, ImageButton, CheckBox这些控件,对其设置android:contentDescription属性。

  • 对于EditText,设置其android:hint属性。

  • 对于其他有交互作用但没有显式文本的控件(比方说可以点击的icon之类),设置其android:hint属性。

以上这些建议的目的,无非就是可以让我们通过自动化测试API去找到页面上的控件。

UI Automator测试流程

使用UI Automator进行脚本编写的一些前置条件和Espresso基本类似,实际上,我们基于之前几篇文章的配置就可以直接进行UI Automator的编写。

采用UI Automator的过程如下:

  • 获得一个UiDevice对象,代表我们正在执行测试的设备。该对象可以通过一个getInstance()方法获取,入参为一个Instrumentation对象:

UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
  • 通过findObject()方法获取到一个UiObject对象,代表我们需要执行测试的UI组件。

  • 对该UI组件执行一系列操作。

  • 检查操作的结果是否符合预期。

整个流程和Espresso基本类似,除了增加了第一项:首先获得一个UiDevice对象。这一点也容易理解,为了要支持跨APP的测试,我们就不能只从APP层面而是需要从整个设备层面来进行测试了,因此也是首先需要获取设备对象,再执行相关的操作。

获取UI组件

根据如上所说,我们是通过UiDevice来调用findObject()方法来获取到我们想要执行操作的UI组件。我们来看一下这个方法的声明:

/**
 * Returns a UiObject which represents a view that matches the specified selector criteria.
 *
 * @param selector
 * @return UiObject object
 */
public UiObject findObject(UiSelector selector) {
    return new UiObject(this, selector);
}

从如上声明可以看出,findObject()方法接受了一个UiSelector对象,返回了我们需要的UiObject对象。在这里,UiSelector类似于Espresso中的Matcher,也是指定了某种匹配规则,UI Automator会按照UiSelector指定的规则从当前UI上进行控件的查找。不同于Espresso的是,如果找到多个满足规则的控件,则会返回第一个控件。如果没有控件满足当前指定的规则,则会抛出一个UiAutomatorObjectNotFoundException异常。

Espresso类似,我们可以通过IDtext等属性来进行控件的查找,同时也可以指定目标控件的类型。可以指定一个规则,也可以通过链式调用指定多个规则。比如:

UiObject mCameraSureBtn = mDevice.findObject(new UiSelector().resourceId("com.android.camera:id/v6_btn_done")
                .className("android.widget.ImageView"));

这行代码的UiSelector构建就是采用了如下两个组合规则:

  • 控件ID"com.android.camera:id/v6_btn_done",这个ID是从某个MIUI版本系统的系统相机获取的,对应于拍照按钮;

  • 控件类型为ImageView

除了UiObject之外,UI Automator还提供了其他的UI对象,比如UiCollection对象可以对一组控件之间进行操作,对布局之间的包含关系做了支持;比如UiScrollable对象支持了对可滑动组件的支持。这些组件的用法大同小异,可以自行参考API接口。

执行操作

找到了我们需要的控件,接下来该对控件进行操作了!

UiObject提供了一系列方法用来执行各种各样的操作。比如:

  • click():点击控件中心;

  • dragTo():拖动控件到指定位置;

  • setText():对可输入控件设置文本;

  • swipeUp():对控件执行上滑操作。类似地,swipeDown(), swipeLeft()swipeRight()可以执行相应的操作

这一部分也是比较简单,和Espresso的用法大体类似,只是API层面的区别。具体的可以在使用的时候查看API文档。

检查结果

执行一系列操作之后,我们需要对操作的结果进行验证了!
对于结果的验证,我们可以使用之前说到的一系列Assert方法了。比如说,我们需要检测某个控件的文字:

assertEquals(TargetText, mUiObject.getText())

便可以这样进行执行。

总结

从该篇文章来看,UI Automator的使用方法和Espresso基本相同,整体的思路也是完全一致,只是一个对APP内部提供了很好的支持,另一个对跨APP提供了支持。大家在实际编写自动化测试脚本时可以灵活选用。

附录

Android自动化测试-从入门到入门(1) Hello Testing!
Android自动化测试-从入门到入门(2) Testing APIs
Android自动化测试-从入门到入门(3) Espresso入门
Android自动化测试-从入门到入门(4) uiautomatorviewer
Android自动化测试-从入门到入门(5) AdapterView的测试
Android自动化测试-从入门到入门(6) 会玩的Espresso
Android自动化测试-从入门到入门(7) UI Automator


Anchorer
431 声望84 粉丝

Show what you're made of.