Introduction: Espresso Testing for Android
We take a look at the Espresso framework and how to write the Java code you need to started testing your Android-based mobile apps.
Join the DZone community and get the full member experience.
Join For FreeAs mobile developers, we spend most of our time creating new screens or changing screens that already exist and we need to know that the code works. That is why in our development process we must use tools to verify that our application continues to work as expected and that our development meets the quality expectation of the user story. So, in this article, we will talk about Espresso Testing.
We need to ensure that:
- we show the correct information to the user when the UI is loaded.
- we show the desired message or screen when the user performs an action.
To meet this objective there are several types of UI tests:
- Classic UI testing -> focuses on views and their interactions.
- Snapshot testing -> guarantees the perfect design, leaving interactions aside.
What Is Espresso Testing? How Does it Work?
Espresso is a framework created by Google for Android that allows us to write tests on the user interface. It has a simple API, easily adapts to our needs, and eliminates the complexity of managing different threads.
Espresso Testing works basically in three blocks:
- ViewMatchers – allows you to find an item in the view.
- ViewActions – allows you to execute actions on the elements.
- ViewAssertions – allows you to validate a view state.
Configuration
To make Espresso Testing work in our project, we need to add the dependencies in our ‘app/build.gradle’ file and a physical or virtual device.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
// Android runner and rules support
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
// Espresso
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
It is recommended to turn off the animations of our Android device that we will use for the tests in the developer options. An easy way to do it is by executing these commands from your terminal:
adb shell settings put global window_animation_scale 0.0
adb shell settings put global transition_animation_scale 0.0
adb shell settings put global animator_duration_scale 0.0
Implementation
As a small practical exercise, we have created a view with two textviews and a button where we want to evaluate that when we press the button a textview is hidden and another one is shown.
We can create our UI test manually or automatically using Espresso's record tool.
Record Espresso
For this, we must go to the options bar of Android studio and choose Run -> Record Espresso Test.
It will launch a screen where we can go making assertions.
And at the end we will generate the test code:
@LargeTest
@RunWith(AndroidJUnit4.class)
public class RecordedTextViewToggleVisibilityTest {
@Rule
public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
@Test
public void textViewToggleVisibilityTest() {
ViewInteraction textView = onView(
allOf(withId(R.id.tv_hello), withText("Hello buddy!"),
childAtPosition(
childAtPosition(
withId(android.R.id.content),
0),
0),
isDisplayed()));
textView.check(matches(withText("Hello buddy!")));
ViewInteraction appCompatButton = onView(
allOf(withId(R.id.button), withText("click me"),
childAtPosition(
childAtPosition(
withId(android.R.id.content),
0),
2),
isDisplayed()));
appCompatButton.perform(click());
ViewInteraction textView2 = onView(
allOf(withId(R.id.tv_see_you), withText("See you"),
childAtPosition(
childAtPosition(
withId(android.R.id.content),
0),
1),
isDisplayed()));
textView2.check(matches(isDisplayed()));
}
private static Matcher childAtPosition(
final Matcher parentMatcher, final int position) {
return new TypeSafeMatcher() {
@Override
public void describeTo(Description description) {
description.appendText("Child at position " + position + " in parent ");
parentMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
ViewParent parent = view.getParent();
return parent instanceof ViewGroup && parentMatcher.matches(parent)
&& view.equals(((ViewGroup) parent).getChildAt(position));
}
};
}
}
Manual form
@LargeTest
@RunWith(AndroidJUnit4.class)
public class ManualTextViewToggleVisibilityTest {
@Rule
public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
@Test
public void textViewToggleVisibilityTest() {
// here we are going to look in the view tree
// we use allOff from hamcrest library to combine matchers
ViewInteraction tvHello = onView(allOf(withId(R.id.tv_hello),withText(R.String.hello_buddy)));
ViewInteraction tvSeeYou = onView(allOf(withId(R.id.tv_see_you),withText(R.String.see_you)));
// assert that textView with text 'Hello buddy!' is display
tvHello.check(matches(isDisplayed()));
// assert that textView with text 'See you' has visibility gone
tvSeeYou.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
// find button with given id and click
onView(withId(R.id.button)).perform(click());
// assert see you is visible and hello buddy is not. tvHello.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
tvSeeYou.check(matches(isDisplayed()));
}
}
We can verify that Espresso has automatically generated more code, which can be easily broken and will require more maintenance. For example, we used the literal string to find the view, and, if we change the language to the device the test would fail. However, we can manually use the id of the string resource and add as many matchers as we need.
This Hamcrest reference guide can be useful when working with matchers.
Conclusion: Espresso Testing
As humans, we are prone to make mistakes and this implies that our software is vulnerable to bugs and defects. Espresso helps us detect errors that may have been made in the development, ensuring the reliability of the client and their satisfaction with the application.
If you have not yet added Espresso to your development tools, think about the people who will have to test the application manually.
Published at DZone with permission of Antoni Sanchez. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments