This document describes how to set up a variety of common Espresso tests.

Matching a view next to another view

A layout could contain certain views that are not unique by themselves. For
example, a repeating call button in a table of contacts could have the same
R.id, contain the same text, and have the same properties as other call
buttons within the view hierarchy.

For example, in this activity, the view with text "7" repeats across multiple
rows:

Often, the non-unique view will be paired with some unique label that’s located
next to it, such as a name of the contact next to the call button. In this case,
you can use the hasSibling() matcher to narrow down your selection:

Matching a view that is inside an action bar

The ActionBarTestActivity has two different action bars: a normal ActionBar and a contextual action bar that is created from a options menu. Both action bars have one item that is always visible and two items that are only visible in overflow menu. When an item is clicked, it changes a TextView to the content of the clicked item.

Matching visible icons on both of the action bars is straightforward, as shown
in the following code snippet:

public void testClickActionBarItem() {
// We make sure the contextual action bar is hidden.
onView(withId(R.id.hide_contextual_action_bar))
.perform(click());
// Click on the icon - we can find it by the r.Id.
onView(withId(R.id.action_save))
.perform(click());
// Verify that we have really clicked on the icon
// by checking the TextView content.
onView(withId(R.id.text_action_bar_result))
.check(matches(withText("Save")));
}

The code looks identical for the contextual action bar:

public void testClickActionModeItem() {
// Make sure we show the contextual action bar.
onView(withId(R.id.show_contextual_action_bar))
.perform(click());
// Click on the icon.
onView((withId(R.id.action_lock)))
.perform(click());
// Verify that we have really clicked on the icon
// by checking the TextView content.
onView(withId(R.id.text_action_bar_result))
.check(matches(withText("Lock")));
}

Clicking on items in the overflow menu is a bit trickier for the normal action
bar as some devices have a hardware overflow menu button, which opens the
overflowing items in an options menu, and some devices have a software overflow
menu button, which opens a normal overflow menu. Luckily, Espresso handles that
for us.

For the normal action bar:

public void testActionBarOverflow() {
// Make sure we hide the contextual action bar.
onView(withId(R.id.hide_contextual_action_bar))
.perform(click());
// Open the options menu OR open the overflow menu, depending on whether
// the device has a hardware or software overflow menu button.
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
// Click the item.
onView(withText("World"))
.perform(click());
// Verify that we have really clicked on the icon by checking
// the TextView content.
onView(withId(R.id.text_action_bar_result))
.check(matches(withText("World")));
}

This is how this looks on devices with a hardware overflow menu button:

For the contextual action bar it is really easy again:

public void testActionModeOverflow() {
// Show the contextual action bar.
onView(withId(R.id.show_contextual_action_bar))
.perform(click());
// Open the overflow menu from contextual action mode.
openContextualActionModeOverflowMenu();
// Click on the item.
onView(withText("Key"))
.perform(click());
// Verify that we have really clicked on the icon by
// checking the TextView content.
onView(withId(R.id.text_action_bar_result))
.check(matches(withText("Key")));
}
}

Asserting that a view is not displayed

After performing a series of actions, you will certainly want to assert the
state of the UI under test. Sometimes, this may be a negative case, such as when
something is not happening. Keep in mind that you can turn any hamcrest view
matcher into a ViewAssertion by using ViewAssertions.matches().

In the example below, we take the isDisplayed() matcher and reverse it using
the standard not() matcher:

Asserting that a data item is not in an adapter

To prove a particular data item is not within an AdapterView you have to do
things a little differently. We have to find the AdapterView we’re interested
in and interrogate the data its holding. We don’t need to use onData().
Instead, we use onView() to find the AdapterView and then use another
matcher to work on the data inside the view.

This failure handler throws a MySpecialException instead of a
NoMatchingViewException and delegates all other failures to the
DefaultFailureHandler. The CustomFailureHandler can be registered with
Espresso in the setUp() method of the test:

Targeting non-default windows

Android supports multiple windows. Normally, this is transparent to the users
and the app developer, yet in certain cases multiple windows are visible, such
as when an auto-complete window gets drawn over the main application window in
the search widget. To simplify things, by default Espresso uses a heuristic to
guess which Window you intend to interact with. This heuristic is almost
always good enough; however, in rare cases, you’ll need to specify which window
an interaction should target. You can do this by providing your own root window
matcher, or Root matcher:

Matching a header or footer in a list view

Headers and footers are added to ListViews using the addHeaderView() and
addFooterView() methods. To ensure Espresso.onData() knows what data object
to match, make sure to pass a preset data object value as the second parameter
to addHeaderView() and addFooterView(). For example: