Espresso simple UI test
suggest changeUI 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:
- Developer options / Disable Animations - reduces flakyness of tests
- Developer options / Stay awake - if you have dedicated devices for tests this is usefull
- Developer options / Logger buffer sizes - set to higher number if you run very big test suites on your phone
- Accessibility / Touch & Hold delay - long to avoid problems with tapping in espresso
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:

- text input field - R.id.textEntry
- button which shows snackbar with typed text when clicked - R.id.shownSnackbarBtn
- snackbar which should contain user typed text - android.support.design.R.id.snackbar_text
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