The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Testing with Espresso

Basic JUnit4 instrumentation tests are fine for testing non-UI logic. They even work acceptably for some basic UI testing. The more complex your UI testing gets, though, the more likely it is that you will find plain JUnit4 instrumentation tests to be limiting and tedious.

In particular, running tests across activities can be tricky with ordinary JUnit4. ActivityTestRule is designed for testing a single activity in isolation, and crafting your own rule that transcends a single activity may be difficult.

Espresso is designed to simplify otherwise-complex UI testing scenarios, such as:

In this chapter, we will explore how to set up basic Espresso tests and how to employ them as part of your overall testing implementation.

Prerequisites

This chapter assumes that you have read the chapter on JUnit4.

Adding a Shot of Espresso

The Testing/Espresso sample project is the home of several test cases that employ Espresso, so we can see how it works in practice.

The app/ module’s build.gradle file is fairly conventional, reminiscent of our JUnit4 equivalent, except that we have several dependencies:

apply plugin: 'com.android.application'

dependencies {
    androidTestCompile 'com.android.support:support-annotations:25.0.2'
    androidTestCompile 'com.android.support:recyclerview-v7:25.0.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
    compile 'com.android.support:recyclerview-v7:25.0.2'
}

android {
    compileSdkVersion 24
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 22
        applicationId "com.commonsware.android.espresso"
        testApplicationId "com.commonsware.android.espresso.test"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments disableAnalytics: 'true'
    }

    packagingOptions {
        exclude 'LICENSE.txt'
    }
}

The sample app has activities for a ListView and a RecyclerView, and so we compile in the recyclerview-v7 dependency for that reason. However, beyond that, there are four androidTest dependencies, to pull in things needed for instrumentation testing.

The big one is espresso-core, which contains the bulk of the Espresso test engine. Through Gradle’s transitive dependencies, pulling in espresso-core also pulls in other key testing artifacts, such as:

Hence, just by asking for espresso-core, we pull in everything that we need not only for basic Espresso testing but also for general JUnit4-style instrumentation testing.

However, the support-annotations requested by espresso-core is an older version than the one that we are using in our code under test. So, we specifically pull in the newer support-annotations, allowing Gradle’s dependency resolution to handle the version discrepancy.

The espresso-contrib and recyclerview-v7 androidTest dependencies are for testing RecyclerView. Those artifacts will be discussed later in this chapter.

The test cases themselves still reside in the androidTest/ sourceset and still use @RunWith(AndroidJUnit4.class). Those aspects of instrumentation testing have not changed, just because we are using Espresso. And we are able to write classic Espresso-free instrumentation tests as well — we are not forced to use Espresso for everything, just because Espresso is part of our environment. So, for example, SillyTest in this sample project is the same as before:

package com.commonsware.android.abf.test;

import android.support.test.runner.AndroidJUnit4;
import junit.framework.Assert;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class SillyTest {
  @BeforeClass
  static public void doThisFirstOnlyOnce() {
    // do initialization here, run once for all SillyTest tests
  }

  @Before
  public void doThisFirst() {
    // do initialization here, run on every test method
  }

  @After
  public void doThisLast() {
    // do termination here, run on every test method
  }

  @AfterClass
  static public void doThisLastOnlyOnce() {
    // do termination here, run once for all SillyTest tests
  }

  @Test
  public void thisIsReallySilly() {
    Assert.assertEquals("bit got flipped by cosmic rays", 1, 1);
  }
}

Writing Tests in Espresso

The preview of this section was abducted by space aliens.

The Espresso Test Recorder

The preview of this section is en route to Mars.

Stronger Espresso

The preview of this section was lost in the sofa cushions.

Opting Out of Analytics

The preview of this section is sleeping in.

Waiting for the World to Change

The preview of this section is unavailable right now, but if you leave your name and number at the sound of the tone, it might get back to you (BEEEEEEEEEEEEP!).