I am trying to click on a text in a list view using Espresso. I know they have this guide, but I can't see how to make this work by looking for text. This is what I have tried
Espresso.onData(Matchers.allOf(Matchers.is(Matchers.instanceOf(ListView.class)), Matchers.hasToString(Matchers.startsWith("ASDF")))).perform(ViewActions.click());
As expected, this didn't work. The error said no view in hierarchy. Does anyone know how to select a String? ("ASDF"
in this case) Thanks in advance.
I received error:
com.google.android.apps.common.testing.ui.espresso.AmbiguousViewMatcherException: 'is assignable from class: class android.widget.AdapterView' matches multiple views in the hierarchy.
With this code
onData(hasToString(startsWith("ASDF"))).inAdapterView(withContentDescription("MapList")).perform(click());
I get this error
com.google.android.apps.common.testing.ui.espresso.PerformException: Error performing 'load adapter data' on view 'with content description: is "MapList"'.
Caused by: java.lang.RuntimeException: No data found matching: asString(a string starting with "ASDF")
onData(anything()).inAdapterView(withContentDescription("desc")).atPosition(x).perform(click())
Here’s how to test this with Espresso: The first step is to look for a property that helps to find the button. The button in the SimpleActivity has a unique R.id, as expected. Now to perform the click: The TextView with the text to verify has a unique R.id too: Now to verify the content text:
As learned earlier, view actions automate all the possible actions performable by users in an android application. Espresso onView and “onData” provides the perform method, which accepts view actions and invokes/automates the corresponding user actions in the test environment.
At the same time, the framework prevents direct access to activities and views of the application because holding on to these objects and operating on them off the UI thread is a major source of test flakiness. Thus, you will not see methods like getView () and getCurrentActivity () in the Espresso API.
For simplicity following String XXYYZZ will be used as a expected text pattern. Espresso ViewMatchers class implements two String matcher methods withText () and withContentDescription () which will match a view which text is equal to specified expectedText or specified expectedContentDescriptionText parameter passed into it.
The problem is, that you try to match the list view itself with the instanceOf(ListView.class)
as argument for onData()
. onData()
requires a data matcher that matches the adapted data of the ListView
, not the ListView
itself, and also not the View
that Adapter.getView()
returns, but the actual data.
If you have something like this in your production code:
ListView listView = (ListView)findViewById(R.id.myListView); ArrayAdapter<MyDataClass> adapter = getAdapterFromSomewhere(); listView.setAdapter(adapter);
Then the Matcher argument of Espresso.onData()
should match the desired instance of MyDataClass
. So, something like this should work:
onData(hasToString(startsWith("ASDF"))).perform(click());
(You can use another Matcher using a method of org.hamcrest.Matchers
)
In case you have multiple adapter views in your activity, you can call ViewMatchers.inAdapterView()
with a view matcher that specifies the AdapterView like this:
onData(hasToString(startsWith("ASDF"))) .inAdapterView(withId(R.id.myListView)) .perform(click());
If adapter have custom model class for example Item
:
public static Matcher<Object> withItemValue(final String value) { return new BoundedMatcher<Object, Item>(Item.class) { @Override public void describeTo(Description description) { description.appendText("has value " + value); } @Override public boolean matchesSafely(Item item) { return item.getName().toUpperCase().equals(String.valueOf(value)); } }; }
Then call following:
onData(withItemValue("DRINK1")).inAdapterView(withId(R.id.menu_item_grid)).perform(click());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With