Android Testing UI with Espresso suggest change

Espresso simple UI test

UI testing tools

Two main tools that are nowadays mostly used for UI testing are Appium and Espresso.

| Appium | Espresso | | —— | —— | | blackbox test | white/gray box testing | |what you see is what you can test|can change inner workings of the app and prepare it for testing, e.g. save some data to database or sharedpreferences before running the test| |used mostly for integration end to end tests and entire user flows|testing the functionality of a screen and/or flow| |can be abstracted so test written can be executed on iOS and Android| Android Only |well supported|well supported| |supports parallel testing on multiple devices with selenium grid| Not out of the box parallel testing, plugins like Spoon exists until true Google support comes out


How to add espresso to the project

dependencies {
  // Set this dependency so you can use Android JUnit Runner
  androidTestCompile 'com.android.support.test:runner:0.5'
  // Set this dependency to use JUnit 4 rules
  androidTestCompile 'com.android.support.test:rules:0.5'
  // Set this dependency to build and run Espresso tests
  androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  // Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.2.2'
}

NOTE If you are using latest support libraries, annotations etc. you need to exclude the older versions from espresso to avoid collisions:

// there is a conflict with the test support library (see http://stackoverflow.com/questions/29857695)
// so for now re exclude the support-annotations dependency from here to avoid clashes
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude module: 'support-annotations'
    exclude module: 'recyclerview-v7'
    exclude module: 'support-v4'
    exclude module: 'support-v7'
}
// exclude a couple of more modules here because of <http://stackoverflow.com/questions/29216327> and
// more specifically of <https://code.google.com/p/android-test-kit/issues/detail?id=139>
// otherwise you'll receive weird crashes on devices and dex exceptions on emulators
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.2') {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude group: 'com.android.support', module: 'design'
    exclude module: 'support-annotations'
    exclude module: 'recyclerview-v7'
    exclude module: 'support-v4'
    exclude module: 'support-v7'
}
//excluded specific packages due to https://code.google.com/p/android/issues/detail?id=183454
androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude module: 'support-annotations'
    exclude module: 'recyclerview-v7'
    exclude module: 'support-v4'
    exclude module: 'support-v7'
}

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

androidTestCompile('com.android.support.test:runner:0.5') {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude module: 'support-annotations'
    exclude module: 'recyclerview-v7'
    exclude module: 'support-v4'
    exclude module: 'support-v7'
}
androidTestCompile('com.android.support.test:rules:0.5') {
    exclude group: 'com.android.support', module: 'support-annotations'
    exclude module: 'support-annotations'
    exclude module: 'recyclerview-v7'
    exclude module: 'support-v4'
    exclude module: 'support-v7'
}

Other than these imports it is necessary to add android instrumentation test runner to build.gradle android.defaultConfig:

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

Device setup

For non flaky test it is recommended to set following settings on your devices:

Quite a setup from the real world ha? Well now when thats out of the way lets take a look how to setup a small test

Writing the test

Lets assume that we have the following screen: The screen contains:

Now lets create a class that will test our flow:

/**
* Testing of the snackbar activity.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
    //espresso rule which tells which activity to start
    @Rule
    public final ActivityTestRule<SnackbarActivity> mActivityRule = 
        new ActivityTestRule<>(SnackbarActivity.class, true, false);
@Override
public void tearDown() throws Exception {
    super.tearDown();
    //just an example how tear down should cleanup after itself
    mDatabase.clear();
    mSharedPrefs.clear();
}

@Override
public void setUp() throws Exception {
    super.setUp();
    //setting up your application, for example if you need to have a user in shared
    //preferences to stay logged in you can do that for all tests in your setup
    User mUser = new User();
    mUser.setToken("randomToken");
}

/**
*Test methods should always start with "testXYZ" and it is a good idea to 
*name them after the intent what you want to test
**/
@Test
public void testSnackbarIsShown() {
    //start our activity
    mActivityRule.launchActivity(null);
    //check is our text entry displayed and enter some text to it
    String textToType="new snackbar text";
    onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
    onView(withId(R.id.textEntry)).perform(typeText(textToType));
    //click the button to show the snackbar
    onView(withId(R.id.shownSnackbarBtn)).perform(click());
    //assert that a view with snackbar_id with text which we typed and is displayed
    onView(allOf(withId(android.support.design.R.id.snackbar_text), 
    withText(textToType))) .check(matches(isDisplayed()));
}
}

As you noticed there are 3-4 things that you might notice come often:

onView(withXYZ) <– viewMatchers with them you are able to find elements on screen

perform(click()) <– viewActions, you can execute actions on elements you previously found

check(matches(isDisplayed())) <– viewAssertions, checks you want to do on screens you previously found

All of these and many others can be found here: https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/index.html

Thats it, now you can run the test either with right clicking on the class name / test and selecting Run test or with command:

./gradlew connectedFLAVORNAMEAndroidTest

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents