Testing Espresso Matchers

If you are using instrumentation tests in your Android app, it is likely that you are using Espresso
— allowing you to define expectations about your app screens and how to interact with them.
During your day-by-day as a developer you will eventually implement some custom views. However, Espresso
won’t have the ability to assert the specific behaviors of your custom view out of the box. To make it possible you will have to create your own Espresso
matchers. In this article I want to show you how to create a simple Matcher and how to run tests for it in the JVM.
The example we will follow is the implementation of a custom Button
that has a loading state. I will break it down into 3 steps: naive implementation of the LoadingButton
, creation of an appropriate Matcher
and the test for that Matcher
. At the end I will just showcase a simple usage of our new tested Matcher.


- Creating the
LoadingButton
For the sake of simplicity I’m not going to focus on the implementation of the LoadingButton.
The only relevant part is that we would have a setter/getter
for the loading state.
2. Creating the WithButtonLoading
Matcher
When creating a custom Matcher
for a custom property of your View
you should extend a BoundedMatcher<T, S extends T>
. When extending it you will have to override two methods:
describeTo(description: Description)
— here you should add a relevant message todescription
so that you can understand better when this matcher assertion fails.matchesSafely(item: S): Boolean
— you should return aBoolean
stating whether or not the givenitem
respects your logic.
In our example we would do as follows:
In this case we would use describeTo
to describe our component (a button in a loading state) and the matchesSafely
to assert that the given item
is in the desired loading state.
An important point is that I actually made this class internal
as this exposes an implementation detail. It is an observed good practice on Espresso
matchers to have public wrappers of the internal matchers that provide friendlier/more readable APIs.
We would then define a public ButtonMatchers
that provides methods to create matchers that check if the button is loading or not loading.
3. Creating the Test
In order to test this matcher in with a fast approach and with no need to run instrumentation tests, we will leverage FragmentScenario
which are able to run on top of JVM. This will create reliable and fast tests when compared with the instrumentation tests.
The idea is that we will use FragmentScenario + Roboelectrict
to launch a Fragment
that inflates our LoadingButton
, so that we can interact with it and perform assertions regarding the Matcher
behavior.
Below you can see that we are testing the behavior of ButtonMatchers.isLoading
matcher: if the Matcher
behaves correctly when the button is loading and not loading.
The magic happens on launchViewInFragment
, which takes a function that creates the View
that will be inflated in the Fragment
.
The internals of launchViewInFragment
make use of FragmentScenario
to setup and launch the test.
If we then run our tests and, the output on Android Studio will be the following:

You can see that it has a initial overheard time spent, but after that the tests run really fast. And the more tests you have the less the overhead will be noticeable in the full test run time.
To finalize I just wanted to briefly show how we would use our new Matchers
in an instrumentation test. In this example, we assume the button loading state is toggled everytime you click it. You can see the matchers being used on the assertButtonIsLoading
and assertButtonIsNotLoading
.
You can find a sample project describing this example here.
References: