Skip to main content
← Blog
Android

How to Do TDD in Android — Part 4: Espresso & UI Tests

2 min read
How to Do TDD in Android — Part 4: Espresso & UI Tests

In this final post of the TDD in Android series, we’ll cover UI testing with Espresso.

To recap: we’ve covered project setup in Part 1, unit tests in Part 2, and mocking with integration tests in Part 3. Now for UI tests.

What is Espresso?

Espresso is Google’s framework for UI testing. It gives you an API to test the UI of an Android app without user intervention. It’s built around three core objects:

  • ViewMatcher — finds a view in the UI using onView()
  • ViewAction — simulates interactions via ViewInteraction.perform()
  • ViewAssertion — verifies view state using ViewInteraction.check()
onView(withId(R.id.my_view))          // ViewMatcher
    .perform(click())                   // ViewAction
    .check(matches(isDisplayed()));     // ViewAssertion

Official Espresso cheat sheet: https://developer.android.com/training/testing/espresso/cheat-sheet.html

Setup

Verify Espresso is in your build.gradle:

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})

Create LoginActivityTest:

@RunWith(AndroidJUnit4.class)
public class LoginActivityTest {
}

Writing UI tests

Every test needs an ActivityTestRule:

ActivityTestRule<LoginActivity> activityTestRule =
    new ActivityTestRule<>(LoginActivity.class);

Check the username field is visible:

@Test
public void checkUserNameEditTextIsDisplayed() {
    activityTestRule.launchActivity(new Intent());
    onView(withId(R.id.txt_user_name)).check(matches(isDisplayed()));
}

Check the password field is visible:

@Test
public void checkPasswordEditTextIsDisplayed() {
    activityTestRule.launchActivity(new Intent());
    onView(withId(R.id.txt_password)).check(matches(isDisplayed()));
}

If you change isDisplayed() to its inverse and run the test, it will fail — a good sanity check.

Verify the error message when submitting empty fields:

@Test
public void checkErrorMessageIsDisplayedForEmptyData() {
    activityTestRule.launchActivity(new Intent());
    onView(withId(R.id.btn_login))
        .check(matches(isDisplayed()))
        .perform(click());
    onView(withText(R.string.error_user_password))
        .check(matches(isDisplayed()));
}

Verify successful login:

@Test
public void checkLoginSuccess() {
    activityTestRule.launchActivity(new Intent());
    onView(withId(R.id.txt_user_name))
        .perform(typeText("user"), closeSoftKeyboard());
    onView(withId(R.id.txt_password))
        .perform(typeText("password"), closeSoftKeyboard());
    onView(withId(R.id.btn_login))
        .check(matches(isDisplayed()))
        .perform(click());
    onView(withText(R.string.login_ok))
        .check(matches(isDisplayed()));
}

Note: UI tests require a physical device or emulator to run.

The project is complete — and fully tested at every level. Now it’s time to apply this in your own projects.

Full source code (Java): https://github.com/jamontes79/TDD_Ejemplo
Kotlin version: https://github.com/jamontes79/TDD_Ejemplo_Kotlin

Hope you found this series useful. Any feedback is welcome.


More in Android