Android UI 测试框架 Espresso

文章一部分转载自InfoQ:http://www.infoq.com/cn/news/2013/10/google-espresso-testing/
一部分转载自 http://www.devtf.cn/?p=168
感谢原创作者,我这里只是整理学习一下,如有不妥,请告知我一下。

Android UI 测试框架 Espresso_第1张图片
Paste_Image.png

Google开源了Espresso,这是一种Android自动化测试框架,Espresso 是在2013年的 GTAC 上首次提出,目的是让开发人员能够快速地写出简洁,美观,可靠的 Android UI 测试。使测试人员可以在云中x86机器的多线程环境里运行测试,并解决了关于UI测试的并发问题。

由于Android设备数量和种类众多,在真实的设备上运行测试非常耗时,而且成本很高。一种解决方案是在模拟器上执行测试。模拟器是一个可控的环境,支持多种OS版本、屏幕尺寸和内存限制。这种方法可以捕获大部分代码Bug,剩下的Bug可以留给真实设备测试和人工测试去发现。

模拟器的问题是执行速度,其中,在模拟的ARM CPU上运行Android是一个瓶颈。为了解决这个问题,Google已经创建了可以直接在x86硬件上运行的Android版本,并使用了VM加速。另一个瓶颈是Android的启动时间。该问题已经通过抓取OS快照并执行快照得以解决。该方法可以在很短的时间内提供期望的OS和应用程序配置。早在今年3月份,Google就已经使用该方法完成了8200万次Android测试。

通过比较在Nexus 4和模拟器上的测试发现,后者需要真实设备上测试时间的65%来完成测试。因此,一个好的模拟器似乎已经解决了自动化测试问题。但是,还有另一块绊脚石。自动化测试使用Android的Instrumentation API,这些API的调用在一个与UI线程不同的线程中运行,因此,使用自动化方法测试用户界面会导致严重的并发问题,进而产生不一致不可靠的测试结果。Google对这个问题的解决方案是Espresso,它是一个测试框架,能够使UI测试在多线程环境中安全地运行,并移除了关于编写测试的大部分样板代码。Espresso可以跨各种移动设备工作,包括电话、电视、智能眼镜、汽车等。它还可以跨不同屏幕尺寸和内存大小、多个API版本以及不同网络工作。据Espresso幕后团队介绍,他们的解决方案捕获了Android和应用程序中99%的Bug,只给真实设备测试和人工测试留下了少数Bug,减少了整体的测试工作量。

Espresso有以下几个通用组件:

“Espresso”类提供的“onView”和“onData”方法,仅可用于特定接口上测试最优数.
ViewMatchers包含一个实现了Matcher 接口的对象集合. 使用该类你可以收集或是检查View元素.例如,通过文本 “7” 获取一个View元素(Button).
ViewActions包含了一组viewAction对象,储存了将要在View上执行的动作. 这些动作被传递给ViewInteraction.perform方法,也许包含更多的动作. For 例如, 点击一下View元素(Button).
ViewAssertions包含ViewAssertion集合,用于对Views进行检查.

下面是Espresso中断言视图未显示的测试示例:
  onView(withId(R.id.bottom_left)).check(matches(not(isDisplayed())));

读者可以在这里找到其它测试示例。

好消息,去年谷歌推出了集成Espresso的Testing Support Library.因此,让我们通过实现Espresso开始吧.
为了方便解释, 我们要编写一些测试用例来测试Android calculator application这个App. 先来实现一个测试“6”x“7”等于“42”是否正确的普通测试场景。

定义test runner

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #454545}span.s1 {font: 12.0px 'PingFang SC'}

使用Espresso我们首先需要定义这些测试用例。Espresso使用新的名为AndroidJUnitRunner的测试用例于“InstrumentationTestRunner”和“GoogleInstrumentationTestRunner”,运行JUnit3和JUnit4来测试你的Android应用程序。
首先将依赖项添加到你的build.gradle文件中, 这里假设你已经安装好了Testing Support Library.

gradledependencies {
androidTestCompile ‘com.android.support.test:testing-support-lib:0.1’
}

然后添加测试用例到你的build.gradleandroid.defaultConfig配置中

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

编写测试
你可能已经想到了,测试类必须在src\androidTest\com.example.package.tests
中.包com.example.package是在AndroidManifest文件中指定的属性.
每一个测试类还必须继承抽象类ActivityInstrumentationTestCase2并且使用默认测试的 Activity 作为泛型.
它还需要通过super()方法传递给父类.要使被测试的Activity被测试框架调用,只需要在setup方法中同步调用getActivity()
方法.

public class FunctionalInstrumentationTest extends ActivityInstrumentationTestCase2 {
 
    public FunctionalInstrumentationTest() {
        super(ActivityToTest.class);
    }
 
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        getActivity();
    }
}

正如前面提到的,我们想要检查“6”x“7”是否等于“42”.

public void testAnswer_to_the_Ultimate_Question_of_Life_the_Universe_and_Everything() {
        onView(withText("7")).perform(click());
        onView(withText("×")).perform(click());
        onView(withText("6")).perform(click());
        onView(withText("=")).perform(click());
 
        onView(withId(R.id.resText)).check(matches(withText("42")));
    }

你可能已经注意到,这个示例是使用静态导入.这样做完全是为了使代码更易于阅读.
其他你可能会用到的操作:

  • pressBack(); to simulate the use of the “back” button,
  • isDisplayed(); to check if an element is being shown and
  • scrollTo(); to scroll to an element.
  • pressBack(); 模拟后退按钮
  • isDisplayed(); jian检查某个元素是否显示
  • scrollTo(); 滚动到另外一个元素
运行测试

现在我们做做有趣的,运行测试.这可以通过gradle clean assembleDebug connectedAndroidTest从命令行运行,或者使用Android Studio:

  • 打开Run菜单 | Edit Configurations
  • 添加一个新的Android Tests configuration
  • 选择你需要测试的Module
  • 定义我们的测试用例: android.support.test.runner.AndroidJUnitRunner
    Google使用Espresso测试了他们自己的超过30个应用程序,包括G+、Maps和Drive。

你可能感兴趣的:(Android UI 测试框架 Espresso)