Code snippets in Espresso

Android Espresso
Here at Brightec we aim to include an extensive range of UI tests with our code. We do this to ensure our code is stable and functioning as expected.
For Android, this comes in the shape of Espresso tests.
The Espresso testing framework gives developers the ‘language’ with which to express their UI test desires.
For the most part, it is reasonably straight forward. However, on rare occasions, or for more obscure UI, it can be difficult to work out the details of the test.
So to help other Android developers, I’ve collated below a (somewhat random) selection of code snippets using Espresso that should be of use to others. Enjoy!
Espresso Snippets
The Espresso framework is extremely powerful but can be quite complex.
Although the Android Studio Test Recorder is improving rapidly, you will still need to tinker your tests manually.
In this post, I am outlining a couple of little snippets of code which I have come across, which might help you in your test writing. These are the ones that I found a bit more tricky or more difficult to find answers to.
Don’t forget to disable animations on the device you are testing on and be sure to check out the test recorder. It is great for creating a starting point for your test and then you can edit it from there.
Spinners
Selecting an item from a spinner is surprisingly easy. It’s simply a case of getting your spinner view (ViewInteraction)
, performing a click and then leveraging the onData
functionality.
ViewInteraction spinner1 = onView(allOf(withId(R.id.spinner_1), withParent(withId(R.id.linear_spinner_parent_1)))); spinner1.perform(scrollTo(), click()); onData(hasToString(stringYouWantToSelect1)).perform(click()); ViewInteraction spinner2 = onView(allOf(withId(R.id.spinner_2), withParent(withId(R.id.linear_spinner_parent_2)))); spinner2.perform(scrollTo(), click()); onData(hasToString(stringYouWantToSelect2)).perform(click());
You can use a few different ways of matching the selection you want but the hasToString
is quite a nice one. And as you can see you can select multiple spinners in one test, the onData
works out which spinner menu is currently showing.
Starting new Activity
Checking a new activity has started can be a vital part of your testing strategy and can be done by creating an ActivityMonitor
and then waitForActivityWithTimeout()
. Then all that’s left is to assert that am.getHits()
equals the number of times your activity should launch i.e. 1.
Instrumentation.ActivityMonitor am = getInstrumentation().addMonitor( NextActivity.class.getName(), null, true); ViewInteraction button = onView(withId(R.id.button_next)); button.perform(scrollTo(), click()); am.waitForActivityWithTimeout(3000); assertEquals(1, am.getHits());Why might you need this? I have used this in order to get hold of a view to use in an idling resource.
public static Activity getActivity() { final Activity[] currentActivity = new Activity[1]; onView(allOf(withId(android.R.id.content), isDisplayed())).perform(new ViewAction() { @Override public Matcher getConstraints() { return isAssignableFrom(View.class); } @Override public String getDescription() { return "Getting activity"; } @Override public void perform(UiController uiController, View view) { if (view.getContext() instanceof Activity) { Activity activity1 = ((Activity) view.getContext()); currentActivity[0] = activity1; } } }); return currentActivity[0]; }
Idling Resources
I have used a couple of different idling resources which are used to effectively wait for something to happen during a test. Hopefully, these will inspire you to write your own. TextViewHasTextIdlingResource.javapublic class TextViewHasTextIdlingResource implements IdlingResource { private final TextView mView; private final boolean mHasText; private boolean mIdle; private ResourceCallback mResourceCallback; public TextViewHasTextIdlingResource(final TextView view, boolean hasText) { this.mView = view; this.mHasText = hasText; this.mIdle = false; this.mResourceCallback = null; } @Override public final String getName() { return TextViewHasTextIdlingResource.class.getSimpleName(); } @Override public final boolean isIdleNow() { mIdle = mIdle || (mHasText != Strings.isNullOrEmpty(mView.getText().toString())); if (mIdle && mResourceCallback != null) { mResourceCallback.onTransitionToIdle(); } return mIdle; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { mResourceCallback = resourceCallback; } }ViewVisibilityIdlingResource.java
public class ViewVisibilityIdlingResource implements IdlingResource { private final View mView; private final int mExpectedVisibility; private boolean mIdle; private IdlingResource.ResourceCallback mResourceCallback; public ViewVisibilityIdlingResource(final View view, int expectedVisibility) { this.mView = view; this.mExpectedVisibility = expectedVisibility; this.mIdle = false; this.mResourceCallback = null; } @Override public final String getName() { return ViewVisibilityIdlingResource.class.getSimpleName(); } @Override public final boolean isIdleNow() { mIdle = mIdle || mView.getVisibility() == mExpectedVisibility; if (mIdle && mResourceCallback != null) { mResourceCallback.onTransitionToIdle(); } return mIdle; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { mResourceCallback = resourceCallback; } }ViewHasChildrenIdlingResource.java
public class ViewHasChildrenIdlingResource implements IdlingResource { private final ViewGroup mView; private final int mExpectedNoOfChildren; private boolean mIdle; private ResourceCallback mResourceCallback; public ViewHasChildrenIdlingResource(final ViewGroup view, int noOfChildren) { this.mView = view; this.mExpectedNoOfChildren = noOfChildren; this.mIdle = false; this.mResourceCallback = null; } @Override public final String getName() { return ViewHasChildrenIdlingResource.class.getSimpleName(); } @Override public final boolean isIdleNow() { mIdle = mIdle || mView.getChildCount() >= mExpectedNoOfChildren; if (mIdle && mResourceCallback != null) { mResourceCallback.onTransitionToIdle(); } return mIdle; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { mResourceCallback = resourceCallback; } }
TextView Url
To test clicking on a URL within a text view tries to open that URL you can do the following:ViewInteraction textView = onView( allOf(withId(R.id.text_info), withParent(withId(R.id.relative_main)))); textView.perform(ViewActions.openLinkWithText("terms and conditions")); intended(allOf(hasAction(Intent.ACTION_VIEW), hasData(Uri.parse("http://www.google.co.uk"))));
Looking for something else?
Search over 400 blog posts from our team
Want to hear more?
Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!