相关文章推荐
踢足球的领结  ·  express server ...·  2 年前    · 
果断的土豆  ·  讲座活动 - ...·  2 年前    · 
首发于 Android
Android自动化测试入门(二)UI Automator

Android自动化测试入门(二)UI Automator

UI Automator是一个界面测试框架,支持跨进程,几乎可以模拟所有的人工操作。需要运行在4.3或者更高的系统版本上。它的测试代码的编写不依赖于目标应用的内部实现细节,非常适用编写黑盒自动化测试。

官方文档

UI Automator 测试框架的主要功能包括:

  • uiautomatorviewer: 用来扫描和分析当前设备的当前页面的布局结构,它是sdk中自带的工具位置在 sdk/tools/bin/uiautomatorviewer.bat
  • UiDevice:可以访问目标设备的各种属性,执行设备上的一些操作,比如获取设备的屏幕尺寸,旋转设备,点击设备的返回键,菜单键,home键等。比如点击home键 UiDevice.pressHome()
  • UI Automator API:用来编写可靠的测试

UI Automator API中有几个比较重要的类

  • UiObject:代表设备上可见的界面元素,也就是一个一个的控件
  • UiObject2:也是代表界面上的一个元素,它和特定的视图绑定,如果所绑定的视图失效,它也会跟着失效。
  • UiSelector:主要封装了用于界面定位的一系列的方法,主要通过控件的属性来实现控件的定位,用来定位的属性一般有: Text,descirption,class,package,resource-id 等。如果搜索到多个满足条件的控件,会返回第一个。属性的搜索可以叠加搜索,比如使用Text筛选出一组控件,还可以使用descirption继续筛选。一般配合UiObject来使用,最终返回一个UiObject对象
  • UiCollection:按照一定的条件列举出界面中所有符合条件的元素,然后在根据内容的文本或者可见内容描述来定位界面上的一个控件或者一个元素。UiCollection对应Android中的ViewGrop
  • UiScrollable:用来处理可滚动控件的滚动操作。
  • Configurator:用来设置用于运行 UI Automator测试的关键参数

官方demo

下面开始使用UI Automator来测试一下系统的计算器,完成一个1+9=10的操作。虽然前面介绍了一堆UI Automator API相关的类,不过用起来的时候很简单,使用官方封装的By类可以很方便的找到对应的界面元素。

打开AndroidStudio,新建一个项目,首先在app下的build.gradle中引入UI Automator的依赖:

androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'

当新建完一个项目的时候,会看到项目中有两个测试相关的文件夹 app/src/androidTest app/src/test

  • app/src/androidTest 主要是运行在真实手机或者模拟器上的测试,比如集成测试,端到端测试,以及仅靠JVM无法完成的功能验证测试
  • app/src/test 在本地计算机上运行的测试,比如单元测试

UI Automator属于运行在手机端,所以去项目中找到app/src/androidTest目录,在这里面就可以编写UI Automator的测试代码了。新建一个测试类CalculateTest

//执行单元测试的执行类
@RunWith(AndroidJUnit4.class)
//4.3以上系统可以使用
@SdkSuppress(minSdkVersion = 18)
public class CalculateTest {......}
  • 指定执行单元测试的执行类为AndroidJUnit4
  • 限制最小运行的sdk是18

一个测试类主要包括三部分,分别用3个注解表示: - @Before 测试之前执行,一般用来创建对象或者一些准备工作 - @Test 用来标注测试方法,可以有多个 - @After 测试完成之后执行,可以做一些清理工作

想要定位界面上的一个元素,可以通过它的resource-id,包名,文本,类名,内容等信息来定位,如果要测试的应用没有源码,可以通过uiautomatorviewer.bat来获取如下图,点击某个元素,右边就会显示出它的一些信息。

//执行单元测试的执行类
@RunWith(AndroidJUnit4.class)
//4.3以上系统可以使用
@SdkSuppress(minSdkVersion = 18)
public class CalculateTest {
     private UiDevice mUiDevice;
     //测试执行之前的操作
    @Before
    public void startMainActivityFromHomeScreen() {
        mUiDevice = UiDevice.getInstance(getInstrumentation());
        //点击home键
        mUiDevice.pressHome();
        // 获取启动页的包名,并判断是否为空
        final String launcherPackage = getLauncherPackageName();
        assertThat(launcherPackage, notNullValue());
        //等待启动完成
        mUiDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), 3000);
        //启动计算器程序
        Context context = getApplicationContext();
        //通过包名创建启动的intent
        Intent intent = context.getPackageManager()
                .getLaunchIntentForPackage("com.android.calculator2");
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
        //等待启动完成
        mUiDevice.wait(Until.hasObject(By.pkg("com.android.calculator2").depth(0)),3000);
    @Test
    public void calculate() throws InterruptedException, UiObjectNotFoundException {
        //点击1
        Thread.sleep(1000);
        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_1);
        Thread.sleep(1000);
        //点击加号
        mUiDevice.findObject(By.res("com.android.calculator2:id/op_add")).click();
        Thread.sleep(1000);
        //点击9
        mUiDevice.findObject(By.text("9")).click();
        Thread.sleep(1000);
        //点击等号
        mUiDevice.findObject(By.desc("等于")).click();
        Thread.sleep(1000);
        //断言验证结果是否正确
        //模拟器
        UiObject2 result = mUiDevice.findObject(By.res("com.android.calculator2:id/result"));
        //华为mate20
//        UiObject2 result = mUiDevice.findObject(By.res("com.android.calculator2:id/formula"));
        //使用UiSelector的方式查找
//        UiObject result = mUiDevice.findObject(new UiSelector().resourceId("com.android.calculator2:id/result"));
        Assert.assertEquals("10",result.getText());
    @After
    public void clearNum() {
        //测试完成之后,点击clear键清除界面上是数字
        //模拟器
        mUiDevice.findObject(By.res("com.android.calculator2:id/clr")).click();
        //华为mate20
//        mUiDevice.findObject(By.res("com.android.calculator2:id/op_clr")).click();
     * 获取程序的启动包名
     * @return
    private String getLauncherPackageName() {
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);