Why not? I’m serious. There’s so much about it that makes it a delight to use:
- Hamcrest Matching
- Simple syntax
- Easy Extensibility
I toiled around a lot with the native Android instrumentation library before taking to Espresso and, I have to say, the difference is substantial.
Don’t put it off like I did, try it out now.
Prepping Your Tools
This tutorial assumes you’re using Android Studio. If you’re not, you should go download it or convince your boss it’s 10,000 times better than Eclipse (it’s free!).
Make Sure the Android Support Library’s Installed
By default, Android Studio will come with some version of the Android support library. What it doesn’t come with it, is the support repository. You can download/update both from the SDK Manager.
From the menu bar, click Tools, then hover over Android.
From the sub-menu, select SDK Manager. You’ll see an Android Studio dialog, but just go ahead and select Launch the standalone SDK Manager.
Scroll down to the bottom, under Extras. You’ll want to make sure the following are checked,
Then, click Install Packages. Accept the licenses, and so on.
Check That You Have an
As of Android Studio 1.5, new projects will be created with three
You want to make sure these exist at
Your Espresso tests are considered instrumentation tests, so they go into the
In Android Studio 2.+, both the androidTest and test packages will be visible at the same time (nice)
Add Gradle Dependencies
Now that your SDK has the support packages, you can just straight up add them to gradle as dependencies.
In your module level
build.gradle, add the following to the
To run Espresso tests, you use the
AndroidJUnitRunner as your instrumentation runner. Add this in the same
And that’s it! You can now write Espresso tests. Let’s not dally.
Brewing Your First Shot
So, I’m not going to be posting the layout XML and Activity here, but you can view them along with the test classes in this gist. Essentially, we’re writing tests for an Activity with a
Creating Your Test Class
All Espresso test classes must extend
T specifies the
Activity you’re testing. The
super constructor takes in a
@RunWith(AndroidJUnit4.class) annotation tells the compiler to build the test class against the
Then, in order to make sure your test is properly injected and you get a reference to the
Activity instance, override the
setUp method. Here, you’ll want to keep a reference to the
Writing the Simplest Espresso Test
So, if you tried to run the code above, you’ll see it fail and tell you that you have no test cases. Let’s fix that.
All test methods can be specified with the
@Test annotation, or have the name prefixed by test.
In your test class, add the following method.
This is the barebones of a runnable test class. You can try to run your test by right-clicking it in the project view and selecting Run ‘MyActivityTest’.
It should say something like
Done: 1 of 1 SUCCESS (if everything was setup correctly).
Make Your Test Do Something
Now, let’s fill up that test case. Add the following static imports to your class.
Android Studio can’t always derive what methods from what classes you’re trying to use. Plus, prefixing everything with
Espresso.* is too much of a hassle. Thus, static imports. They can be trimmed as needed.
In newer versions of Android Studio, you can hover over unknown method calls and press Alt+Enter to bring up the suggestions menu. Select “Static import…”. This will add the static imports for you.
So, let’s look at our first bit of Espresso code.
If you think it reads like a sentence, that’s exactly the intention. Hamcrest matchers and the Espresso library are both designed to be human-readable.
Though, knowing how to read isn’t the only requisite. There’s a bit of context to the pattern used when Espresso testing.
A Little More Context
So, there’s three major components to Espresso testing:
- Espresso Methods
If you look at the code above, you’ll see that
check are Espresso methods.
withId are both Matchers.
click is an Action.
matches is an assertion that takes in
isDisplayed, another matcher.
Getting a Little Touchy
What if you don’t want to target a specific view? Like you just want to swipe stuff? You can do that, too.
In fact, the Android Instrumentation library can do that for you, but if you want to use Espresso for it, you’ll need to target a view.
So, make sure you have an ID on the view you want to swipe.
Inserting Text with Espresso
Alright, cool, you can swipe stuff and click stuff. Wow.
Now, what if you wanted to type text? Espresso’s got you covered.
All of the tests so far were dependent on the layouts we’re working with. What if we wanted to do something like rotate the phone? Or just go the Recents view?
While Espresso doesn’t have out-of-the-box support for anything besides
.pressBack(), you can incorporate other testing libraries to cover for it.
Specifically, I’m referring to UiAutomator, a testing library for writing black-box UI tests. It provides methods for pressing various ActionBar buttons (e.g. Back, Home, Recents).
With Espresso, people note that you can match the
ActionBar buttons using their
contentDescriptions. However, this is language specific, so if you’re testing an international app, your tests will fail.
On top of that, you would also have to use something like the uiautomatorviewer to see the View properties.
Before we continue, I want to mention that Espresso doesn’t extensively support all of the new View classes. Specifically, I’m referring to
RecyclerView. This is where the
espresso-contrib dependency comes in- it’s an extension of the core library and comes with the
RecyclerViewActions utility class.
Let’s write a test that clicks on an item in the list of the names.
Take note of how un-Espresso the code looks. There must be a better solution, right? There is.
When you get deeper into Espresso, you’ll learn about more advanced features like custom
Matcher classes. These utilize the same syntax and allow you to customize how
Views are matched and validated against.
At this point, you should be ready to start running with Espresso. Of course, I didn’t cover everything and I strongly encourage going through the documentation and learning of the nifty little functions I didn’t mention.
Happy testing and Godspeed. ;P