How to Test Your Android App Using Espresso

By Michael Burton

As a developer, you already know the importance of writing tests for your code. This is just as true for Android app development as it is for any other kind of development. Luckily, Android makes it easy to add tests to your app.

The following information will take you through the basics of adding tests to your Android app using Espresso. Espresso is a library that ships with the Android SDK to make testing Android user interfaces simpler.

Just make sure your app is using gradle 2.1.1 or later with Android build tools 21.1.2 or later.

To add an Espresso test to your app, you’ll need to:

  1. Modify your build script

  2. Write the test

  3. Run the test

How to modify your build

Open the build.gradle file for your app. If your app has multiple modules, you’ll want to open the build.gradle file in your app module, not in the root module. So for the Silent Mode Toggle app, you would open SilentModeToggle/build.gradle.

Add the following dependency to the dependencies section of your build.gradle file:

dependencies {
  …
  // Test dependencies
  androidTestCompile 
    'com.android.support.test.espresso:espresso-core:2.0'
}

This tells Android Studio to include the Espresso library in your test dependencies. The Espresso library won’t be built into the apk that you ship, but it will be included in your test apk so that your tests can use it.

Next, add the following to your defaultConfig:

defaultConfig {
  …
  // The test runner to use when running the tests.
  testInstrumentationRunner
    "android.support.test.runner.AndroidJUnitRunner"
}

This tells Android which Instrumentation to use to run your tests. You don’t need to know a lot about the Instrumentation, other than that this is the one you need to use whenever you want to run Espresso tests.

That’s all you need to do to add support for Espresso. Next, you’ll need to write the actual test.

How to write the test

To add a test to Android, you need to make sure you put it in the right location. Open your src directory in Android Studio, and create a new directory named androidTest if it doesn’t already exist. Inside that directory, make a directory named java.

Inside the directory you just created, create a new file named SilentModeToggleEspressoTest.java. You can actually name it whatever you want, just make sure it ends in “Test.java“.

Put the following into your test file:

public class SilentModeToggleEspressoTest
  extends ActivityInstrumentationTestCase2<MainActivity>
{
  public SilentModeToggleEspressoTest() {
    super(MainActivity.class);
  }
}

This creates a new class named SilentModeToggleEspressoTest. It extends ActivityInstrumentationTestCase2, which you’ll use to write most of your app’s tests. ActivityInstrumentationTestCase2 is parameterized on the type of activity you want to test. For the SilentModeToggle app, the app’s main activity is called, appropriately enough, MainActivity.

Your test class needs to have a default constructor, and in that default constructor you’ll call the super class’ constructor with the class of the activity being tested. What you’ve written up until now will basically be copy-pasted for just about every Android test you ever write.

Before you can write your actual test, you’ll need to set it up. To do that, add the following method to your test class:

@Override
  public void setUp() throws Exception {
    super.setUp();
    getActivity();
  }

To test an activity using Espresso, you must first create the activity being tested. This is done by calling getActivity(), which creates and launches the activity for you if it doesn’t already exist. You do this above in the setUp() method for the class, which is run before each of your tests are run.

Now, finally, you can write your test. Add the following method to your class:

public void testPhoneIconIsDisplayed() {
    // When the phone_icon view is available,
    // check that it is displayed.
    onView(withId(R.id.phone_icon))
      .check(matches(isDisplayed()));
  }

You’ll need to import the onView, withId, check, matches, and isDisplayed methods. Android Studio offers to assist you with the necessary static imports.

Espresso tests are designed to be very easy to read. As you can see here, this test is waiting until the view with ID R.id.phone_icon is available, and once it is, it’s checking that the view is displayed.

The next step is to run the test.

How to run the test

First, start up an emulator or connect your phone to your computer via USB.

Once your device is connected and running, right-click on the java directory under androidTest, and then choose Run All Tests (with the Android icon):

image0.png

If the test runs successfully, you should see something like the following:

image1.png

Why are tests important?

Why go through all this effort just to add a simple test? You might think that it hardly seems worth testing such basic functionality.

The Silent Mode Toggle app is simple enough that perhaps a lazy programmer might justify skipping tests. Maybe.

If you add a couple of tests for adding, removing, and editing tasks to that app, you have the peace of mind of knowing that whenever you make a change, your automated tests will catch any significant bugs that you introduce.

Do you really want to re-test all your app’s functionality on phones, tablets, watches, and TVs, and then do it all again on older devices to test backward compatibility? Adding tests can take care of much of that difficulty for you.

About Espresso tests

Espresso tests are written using the following format:

onView( Matcher )
  .perform( ViewAction )
  .check( ViewAssertion )

The following cheat sheet, courtesy of the Espresso 2.0 project, is a helpful tool for writing Espresso tests. It lists out the general syntax for Espresso tests, and it also lists the most common types of matchers: ViewAction and ViewAssertion.

image2.png

A quick way to write Espresso tests is to take advantage of Android Studio’s autocomplete functionality. If you know that most matchers are in the ViewMatchers class, most view actions are in ViewActions, and most view assertions are in ViewAssertions, then you can use autocomplete to find the right matcher:

image3.png

Let’s add one more

So with that in mind, let’s add one more test. Add the lines in bold to your test class:

public class SilentModeToggleEspressoTest
  extends ActivityInstrumentationTestCase2<MainActivity>
{ 
  AudioManager audioManager;
  …
  @Override
  public void setUp() throws Exception {
    super.setUp();
    Activity activity = getActivity();
   
    // Retrieve an AudioManager from the activity
    audioManager = (AudioManager)
      activity.getSystemService(Context.AUDIO_SERVICE);
    // Make sure the ringer mode is reset to normal
    audioManager.setRingerMode(
        AudioManager.RINGER_MODE_NORMAL);
  }
  …
  public void testCanToggleIcon() {
    // When the phone_icon view is available, click it
    onView(withId(R.id.phone_icon)).perform(click());
    // Then assert that the phone is now in silent mode.
    assertTrue(RingerHelper.isPhoneSilent(audioManager));
  }
}

This test finds the toggle button and clicks it, then verifies that the app’s silent mode was turned on. The setUp() code ensures that the ringer mode is reset to normal before the test runs. Now, whenever you make a change to your app, you just need to run these test cases to have the confidence that you haven’t broken anything important.

If you have a continuous integration server, all you need to do is run the connectedCheck target in gradle to run your test cases with every commit you make. If you don’t have a continuous integration server yet, maybe now is a good time to look into one! Check out travis-ci.org for a good option.

Testing apps on Android is a deep and involved topic, but now you should have everything you need to get started testing your apps!

If you’d liked to get more advanced, you may be interested in some of the following resources:

  • Use Spoon to test on multiple device.

  • Try Fork to run tests quickly across multiple devices.

  • Try travis-ci or Jenkins for a continuous integration server.

  • Watch Michael Bailey’s introduction to Android Testing on YouTube.