espresso系列一简介

espresso是什么?

Espresso 测试框架提供了一系列的API用于构建UI测试来测试app内用户流操作。这些API让你可以编写简洁可靠的自动化UI测试。Espresso非常适合用来编写白盒测试,其中测试代码的编写是利用了被测试app中程序代码实现细节。

Espresso测试可运行android 2.3.3(API 10 level)以及更高版本的设备上。使用Espresso的主要好处是,当你运行测试时它提供了自动的同步测试动作与应用程序UI。Espresso会检测你的主线程是否为空闲状态,如果你的没有被利用,这时候他就会抢占主线程运行测试,所以它能够在恰当的时间运行您的测试命令,提高测试的可靠性。这种能力也使您无须添加任何额外的措施,例如在测试代码中加入thread.sleep()

Espresso测试框架基于 instrumentation-based API 并且使用 AndroidJUnitRunner测试驱动运行测试。

Espresso测试框架的关键特性包括:

  • [ ] 提供了灵活的API用于匹配目标app中view和adapter。更多的信息,见View匹配
  • [ ] 大而全的 行为 api(action APIs) 用于自动化UI交互。更多的信息,见行为APIs
  • [ ] UI线程同步来提高测试可靠性。更多信息,见UI线程同步

版本兼容

Espresso 支持如下 API:

代号 API
Froyo 8
Gingerbread 10
Ice Cream Sandwich 15
Jelly Bean 16, 17 ,18
KitKat 19
Lollipop 21

注意:
切记 espresso 有版本断层,并不是全版本支持,请注意你设备android系统的版本,以免造成不必要的免费。
不过最新的android系统版本 espresso都是支持的。

配置espresso

官方文档建议我们在开始配置之前,先看看如何开始测试,我觉得非常有必要,很多新手上来就拿着不知道那找来的例子运行下,就以为自己真的什么都会。这样的真的很不好,官方文档才是最好的老师,让我们一步一步慢慢来。

android是基于JUnit测试框架,单元测试,您可以运行任意本地的单元测试在JVM或instrumented tests在Android设备上。

测试类型

当使用Android studio 编写任何你的测试时,你的测试代码必须进入两个不同的代码目录(源集)。每个模块在您的项目中,Android Studio都包括源集,对应于以下测试类型:

本地单元测试

位于 module-name/src/test/java/.

这些测试运行在本地JVM并没有访问Android框架api功能的权限。
让我们首先开始如何构建本地单元测试。

构建本地单元测试

如果您的单元测试没有依赖或只有简单的依赖Android系统,你应该在本地开发机器上运行您的测试。这种测试方法是有效的,因为它可以帮助你避免加载目标应用程序时的开销以及单元测试需要在一个物理设备或模拟器运行。因此,运行单元测试的时间将大大的减少。使用这种方法,您通常使用mocking 框架,列如Mockito、这可以帮助我们mock测试需要的依赖。

设置测试环境

在你的Android Studio项目时,您必须为本地单元测试存储源文件在 module-name/src/test/java/。当你创建一个新项目,这个目录就已经存在。您还需要为您的项目配置测试依赖,因为需要使用JUnit 4的框架提供标准的api。
如果您的测试需要与Android依赖关系,包括使用Mockito来简化你的单元测试。更多地使用 mock objects在本地的单元测试中,请查看Mocking Android依赖关系。在你的应用程序的顶层目录的build.gradle文件里,您需要指定这些库的依赖关系:

1
2
3
4
5
6
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}

创建本地单元测试类

你当地的单元测试类应该写成一个JUnit 4测试类。JUnit是最受欢迎和广泛使用为Java单元测试框架。这个框架的最新版本,JUnit4,允许您在一个比之前的版更清洁和更灵活的方法中编写测试。之前的Android单元测试基于JUnit3框架,使用JUnit4,您不需要扩展junit.framework。TestCase类。你也不需要在测试方法名称包含“test”关键字,或者使用junit的任何类在junit.framework或junit.extensions包。

创建一个基本的JUnit 4测试类,首先需要创建一个Java类,它包含一个或多个测试方法。一个测试方法以@Test annotation标注并且包含代码的实现和验证的代码中包含您想要测试的一个功能组件。

下面的例子展示了如何实现一个本地的单元测试类。测试方法emailValidator_CorrectEmailSimple_ReturnsTrue验证isValidEmail()方法,应用程序返回正确的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.Test;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EmailValidatorTest {
@Test
public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
}
...
}

测试组件在应用程序返回预期的结果,使用junit.Assert方法来执行验证检查(或断言)来对比测试组件的状态和一些期望值。为了使测试具有更好的可读的,您可以使用Hamcrest matchers(如 is()和equalTo()方法)来匹配返回的结果与预期的结果。

Mock Android依赖关系

默认情况下,Android插件Gradle执行本地的单元测试与修改后的版本的Android.jar库,它不包含任何实际的代码。相反,从你的单元测试方法调用安卓类抛出异常。这确保你的测试代码和不依赖于任何特定的行为的Android平台(你没有显式地mock)。
您可以使用模拟框架在代码中存根外部依赖关系,以便轻松测试您的组件是否按照预期的方式与依赖关系交互。 通过用模拟对象替换Android依赖项,您可以将单元测试与Android系统的其余部分隔离,同时验证这些依赖关系中的正确方法是否被调用。 Java的Mockito mocking框架(1.9.5及更高版本)提供了与Android单元测试的兼容性。 使用Mockito,您可以配置模拟对象以在调用时返回一些特定值。

要使用此框架将mock对象添加到本地单元测试,请遵循以下编程模型:

  • 在build.gradle文件中包含Mockito库依赖关系,如设置测试环境中所述。
  • 在单元测试类定义的开始,添加@RunWith(MockitoJUnitRunner.class)注释。 这个注释告诉Mockito测试运行器验证你的框架的使用是正确的,并简化了你的模拟对象的初始化。
  • 要为Android依赖项创建模拟对象,请在字段声明之前添加@Mock注释。
  • 要存根依赖关系的行为,可以使用when()和thenReturn()方法指定条件并返回值。

以下示例显示如何创建使用mock上下文对象的单元测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import android.content.SharedPreferences;
@RunWith(MockitoJUnitRunner.class)
public class UnitTestSample {
private static final String FAKE_STRING = "HELLO WORLD";
@Mock
Context mMockContext;
@Test
public void readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
when(mMockContext.getString(R.string.hello_word))
.thenReturn(FAKE_STRING);
ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
// ...when the string is returned from the object under test...
String result = myObjectUnderTest.getHelloWorldString();
// ...then the result should be the expected one.
assertThat(result, is(FAKE_STRING));
}
}

要了解有关使用Mockito框架的更多信息,请参阅示例代码中的Mockito API参考和SharedPreferencesHelperTest类。
如果Android.jar中的Android API抛出的异常对于测试有问题,您可以更改行为,以使方法通过在项目的顶级build.gradle文件中添加以下配置来返回null或零:
android { ... testOptions { unitTests.returnDefaultValues = true } }

警告:将returnDefaultValues属性设置为true应该小心。 null/zero 返回值可以在测试中引入回归,这难以调试,并且可能允许失败的测试通过。 只能使用它作为最后的手段。

运行本地测试

要运行本地单元测试,请按照下列步骤操作:

  1. 通过单击工具栏中的 Sync Project,确保您的项目与Gradle同步。
  2. 使用以下方法之一运行测试:
  • 要运行单个测试,请打开“Project”窗口,然后右键单击测试,然后单击RUN。
  • 要测试类中的所有方法,请右键单击测试文件中的类或方法,然后单击Run。
  • 要在目录中运行所有测试,请右键单击目录并选择Run test。
    Gradle的Android插件编译位于默认目录(src / test / java /)中的本地单元测试代码,构建一个测试应用程序,并使用默认的测试运行器类在本地执行它。 然后,Android Studio将在“运行”窗口中显示结果。

Instrumented tests

位于module-name/src/androidTest/java/。
这些都是必须在Android硬件设备或Android模拟器上运行的测试。

仪表化测试内置于在测试下的应用旁边的设备上运行的APK。 系统在同一个过程中运行测试APK和您的应用程序,因此您的测试可以调用方法和修改应用程序中的字段,并自动化用户与您的应用程序的互动。

有关如何创建检测测试的信息,请参阅以下主题:

构建测试单元测试:使用Android依赖项构建复杂的单元测试,这些测试不能满足模拟对象。
自动化用户界面测试:创建测试以验证用户界面在单个应用程序内的用户交互或多个应用程序之间的交互操作正确。
测试应用程序组件集成:验证用户不直接与之交互的组件(例如服务或内容提供者)的行为。

但是,上述的本地单元测试和instrumented tests只是用于区分在本地JVM上运行的测试和在Android平台(在硬件设备或模拟器上)运行的测试之间的术语。 在构建完整测试套件时应该理解的真实测试类型在下表中描述。

Type 子类型 描述
Unit tests Local Unit Tests 本地单元测试在Java虚拟机(JVM)上本地运行的单元测试。当您的测试没有Android框架依赖项或者可以模拟Android框架依赖项时,使用这些测试来最小化执行时间。
Unit tests Instrumented unit tests 测试单元测试在Android设备或模拟器上运行的单元测试。这些测试可以访问Instrumentation信息,例如您要测试的应用程序的上下文。当你的测试有Android依赖,模拟对象不能满足时,使用这些测试。
Integration Tests Components within your app only 您的应用程序中的组件仅当用户执行特定操作或在其活动中输入特定输入时,此类型的测试验证目标应用程序的行为如预期。例如,它允许您检查目标应用程序返回正确的UI输出,以响应用户在应用程序活动中的互动。 Espresso等UI测试框架允许您以编程方式模拟用户操作并测试复杂的应用内用户交互。
Integration Tests Cross-app Components 跨应用程序组件此类型的测试验证不同用户应用程序之间或用户应用程序和系统应用程序之间的交互的正确行为。例如,当用户在Android设置菜单中执行操作时,您可能需要测试您的应用是否正确运行。支持跨应用程序交互的UI测试框架(如UI Automator)允许您为这些场景创建测试。

Test APIs

以下是用于在Android上测试应用的常见API。
JUnit
您应该将您的单元或集成测试类写为JUnit 4测试类。 该框架提供了一种方便的方法来在测试中执行常见的setup, teardown, and assertion操作。

基本的JUnit 4测试类是包含一个或多个测试方法的Java类。 测试方法以@Test注释开始,包含练习和验证要测试的组件中的单个功能(即逻辑单元)的代码。

以下代码段显示了一个示例JUnit 4集成测试,它使用Espresso API对UI元素执行单击操作,然后检查是否显示预期的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
MainActivity.class);
@Test
public void sayHello(){
onView(withText("Say hello!")).perform(click());
onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
}
}

在您的JUnit 4测试类中,您可以通过使用以下注释调用测试代码中的部分进行特殊处理:

  • @Before:使用此注释来指定包含测试设置操作的代码块。测试类在每次测试之前调用此代码块。你可以有多个@Before方法,但是测试类调用这些方法的顺序不能保证。
  • @After:此注释指定一个包含测试拆分操作的代码块。测试类在每个测试方法之后调用这个代码块。您可以在测试代码中定义多个@After操作。使用此注释从内存释放任何资源。
  • @Test:使用此注释标记测试方法。单个测试类可以包含多个测试方法,每个测试方法都以此注释作为前缀。
  • @Rule:规则允许您以可重用的方式灵活地添加或重新定义每个测试方法的行为。在Android测试中,将此注释与Android测试支持库提供的测试规则类之一一起使用,例如ActivityTestRule或ServiceTestRule。
  • @BeforeClass:使用此注释为每个测试类指定仅调用一次的静态方法。此测试步骤对于消耗大的操作(例如连接到数据库)很有用。
  • @AfterClass:使用此注释为测试类指定静态方法,仅在类中的所有测试运行后调用。 这个测试步骤对释放在@BeforeClass块中分配的任何资源很有用。
  • @Test(timeout =):一些注释支持传递元素的能力,您可以为其设置值。 例如,您可以为测试指定超时期限。 如果测试开始,但没有在给定的超时期间内完成,它会自动失败。 您必须以毫秒为单位指定超时期限,例如:@Test(timeout = 5000)。
    使用JUnit Assert类来验证对象状态的正确性。 assert方法将您从测试所期望的值与实际结果进行比较,如果比较失败,则抛出异常。 断言类更详细地描述这些方法。

    Android测试支持库

    Android测试支持库提供了一组API,允许您快速构建和运行应用程序的测试代码,包括JUnit 4和功能UI测试。 库包括以下基于工具的API,当您想要自动化测试时,这些API是有用的:

AndroidJUnitRunner
适用于Android的JUnit 4兼容测试运行器。
espresso
一个UI测试框架; 适用于在应用程序内的功能UI测试。
UI automator
适用于系统和已安装应用程序之间跨应用程序功能UI测试的UI测试框架。

断言类

由于Android测试支持库API扩展JUnit,因此可以使用断言方法显示测试结果。断言方法将测试返回的实际值与预期值进行比较,如果比较测试失败,则抛出AssertionException异常。使用断言比记录更方便,并提供更好的测试性能。

为了简化测试开发,您应该使用Hamcrest库,它允许您使用Hamcrest匹配器API创建更灵活的测试。

Monkey 和 monkeyrunner
Android SDK包含两个用于功能级应用测试的工具:

Monkey
这是一个命令行工具,用于向设备发送按键,触摸和手势的伪随机流。您使用Android Debug Bridge(adb)工具运行它,并使用它来压力测试您的应用程序,报告所遇到的错误,或通过使用相同的随机数种子多次运行该工具来重复事件流。
monkeyrunner
此工具是用Python编写的测试程序的API和执行环境。 API包括用于连接到设备,安装和卸载包,截取屏幕截图,比较两个图像以及针对应用运行测试包的功能。使用API​​,您可以编写大量,强大和复杂的测试。您使用monkeyrunner命令行工具运行使用API​​的程序。

构建Android测试的指南

以下文档提供了有关如何构建和运行各种测试类型的更多详细信息:

建立本地单元测试
构建单元测试没有依赖或只有简单的依赖,你可以mock,它运行在本地JVM上。
建筑仪表单元测试
使用Android依赖项构建复杂的单元测试,这对于在硬件设备或模拟器上运行的模拟对象无法满足。
自动化用户界面测试
创建测试以验证用户界面在单个应用程序内的用户交互或多个应用程序之间的交互正确运行。
测试应用程序集成
验证用户不直接与之交互的组件(例如服务或内容提供者)的行为。
测试显示性能
编写测试应用程序UI性能的测试,以确保持续流畅的用户体验。
ok 我们已经看完了 怎么开始android测试,我想大家一定有了很深入的了解了吧
让我们进入正题 配置espresso
在Android应用程序模块的build.gradle文件中,必须为Espresso引入jar依赖:

1
2
3
4
dependencies {
// Other dependencies ...
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
}

关闭测试设备上的动画 - 在测试设备中打开系统动画可能会导致意外的结果,或可能导致测试失败。 通过打开开发者选项并关闭所有以下选项,从设置中关闭动画:

  • 在设备上的设置->开发者选项中禁用一下三项设置: > 窗口动画缩放 > 过渡动画缩放 > 动画程序时长缩放
  • 确保你已经安装了最新的 Extras 下的 Android Support Repository
    设置junit为测试驱动框架
    在build.gradle 中 添加
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    完整的build.gradle 示例文件如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    ​android.defaultConfigpply plugin: 'com.android.application'
    android {
    compileSdkVersion 24
    buildToolsVersion rootProject.buildToolsVersion
    defaultConfig {
    applicationId "com.example.android.testing.espresso.BasicSample"
    minSdkVersion 10
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    lintOptions {
    abortOnError false
    }
    productFlavors {
    }
    }
    dependencies {
    // App dependencies
    compile 'com.android.support:support-annotations:' + rootProject.supportLibVersion;
    compile 'com.google.guava:guava:18.0'
    // Testing-only dependencies
    // Force usage of support annotations in the test app, since it is internally used by the runner module.
    androidTestCompile 'com.android.support:support-annotations:' + rootProject.supportLibVersion;
    androidTestCompile 'com.android.support.test:runner:' + rootProject.runnerVersion;
    androidTestCompile 'com.android.support.test:rules:' + rootProject.rulesVersion;
    androidTestCompile 'com.android.support.test.espresso:espresso-core:' + rootProject.espressoVersion;
    }

之后我们只需要在命令行中输入gradle就会帮我们下载依赖运行测试了,对了记着要安装gradle到你的系统中.