Dealing with actions and checks on children of a RecyclerView’s item in Espresso tests

Espresso and child.

While writing UI test for Android with Espresso, you might have noticed that dealing with RecyclerViews is not straightforward as with ListViews.

That’s because RecyclerView inherits from ViewGroup and not from AdapterView and thus you can’t do things like

onData(…)

.perform(…)

Fortunately RecyclerViewActions from “espresso-contrib” come in handy, allowing you to doing things like

onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItemAtPosition(3, click()))

to give you an example.

But when it comes to views inside a RecyclerView’s item, how do you deal with it?

Suppose we have a RecyclerView whose items are editable notes and you want to replace the text contained inside the row or want to check if text contained in the EditText of a given row matches what you expected.

You would usually have to create a custom ViewAction implementation for the particular action to take, for instance

and use it in your test code like this

onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItemAtPosition(
3,
TypeTextInChildAction.typeText(R.id.name, "Paolo")
)
)

And what about checking the content of the EditText against a given string?

You will have to create a custom Matcher that scrolls the RecyclerView to the given position and performs a check on the children of the view found, but once again it would not be straightforward and it takes a lot of boilerplate each time.

So I decided to write my code once and use it for all my tests.

Initially I wanted to write extension methods for the RecyclerViewActions class but then I decided to keep things separated and go for a new class named RecyclerViewChildActions which is based on the functionality available in RecyclerViewActions and adds actions and matchers on RecyclerView’s items children.

Basically it implements a custom ViewAction available via the “actionOnChild” method

which takes in a ViewAction and the id of a view to perform the action on.

You can use it as follows

passing it to an action from RecyclerViewActions (actionOnItemAtPosition int the example above).

RecyclerViewChildActions implements a custom matcher too.
It is accessed via the method “childOfViewAtPositionWithMatcher”

and takes in the id of a view which is a descendant of the RecyclerView’s item placed at “position” and a childMatcher to match the view against.

It can be used as follows

directly on the RecyclerView as a parameter to a matches function.

All the above is packed as an android library that you can get via Gradle

implementation 'it.xabaras.android.espresso:recyclerview-child-actions:1.0'

or Maven

<dependency>
<groupId>it.xabaras.android.espresso</groupId>
<artifactId>recyclerview-child-actions</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>

For more detailed information refer to the gitHub repository of the project.

Any suggestion or contribution to extend/improve this api is warmly welcome.