[MUSIC PLAYING]
Writing good tests can be a challenge.
And writing reliable UI tests, it's substantially more
difficult. User interfaces are asynchronous,
driven by events, transitions, and data
loaded from background threads.
Coding around that without any help from a UI testing
framework would require a lot of boilerplate and handling
of edge cases.
On the other hand, say I give you a phone with a sample app
and tell you to test a feature of the app
that I just implemented.
For example, please make sure that saving a new note
in my note-taking app works.
What would you do?
Well, I'm pretty sure that you would look for a Save button.
Once you've found it, you'd tap on it
and then check if the note is present in the list
of saved notes.
That's actually a pretty good scenario for a UI test,
and it's simple to understand for a person.
But how would we go about expressing it in code?
The Espresso framework was created specifically
for this purpose-- to enable developers
to write UI tests that are concise, reliable, and using
a fluent API.
And most importantly, Espresso takes care of synchronization
with any UI events so that, in most cases,
you don't have to worry about any view state transitions
and implementation details.
Looking back at the simple UI test we just defined,
we can see that the basic flow when using Espresso
is exactly the same as in our real-life scenario.
First, find a view using some matching rules.
Then perform an action on it.
And finally, verify the resulting state.
Before I go any further and start writing actual test code,
let's make sure that the Android test
runner and Espresso dependencies are configured in build.gradle.
I'll add the dependencies and set up the runner here.
If you're using a version of Android Studio that
lets you select the test artifact,
remember to switch to Android instrumentation
test under Build Variants.
I'm using Android Studio 2.0, which
has a combined view for both local and instrumentation
tests.
So I can already see both in my project view.
Instrumentation tests go under the Android test source set.
So I'll create a sample test class here
and name it NotesScreenTest.
I have to add an annotation on the test class to specify
that I'll be writing Junit 4 tests
and running them with the Android Junit 4 runner.
The note screen in our app is contained
in the notes activity.
By adding an activity test rule, I'm
telling the runner to launch the activity before any test
and turn it down after they finish.
All of this is taken care of with this line.
Now I'll add a new method with a descriptive
name for the actual test and start with the basic structure
I explained before.
Notice that onView is actually a method on the Espresso class.
But across my testing code, I will use static imports
to be able to express the tests in a more concise way.
All right.
Let's go through the arguments next.
We need a matcher in order to find a view in the current view
hierarchy.
Espresso comes with a set of built-in matchers
for common view properties like With ID, With Text,
Is Checked, and many others.
We provide a simple cheat sheet so you
don't have to go digging through the documentation every time.
In my case, I want to locate the floating action button, which
fortunately is the only item on the screen with the ID
fab_add_notes.
Now that I've isolated the view that I need using matchers,
it's time to apply a view action,
or in other words, a user interaction
that will be simulated by Espresso.
I just want to click the FAB.
But again, there are many more built-in actions, like typing
and even finger swipes, that I can use to interact with views.
And finally, I verify the outcome of my actions
by using a view assertion.
Since I want to check if an input field is shown
on screen after pressing the fab,
I'll move this block of code here.
And I use the matches assertion that accepts a view matcher.
So to summarize what we have so far,
the first statement matches a floating action button
and clicks it, which should bring up the Add Note screen.
The second statement finds the edit text
that lets a user enter a note title
and verifies that it is displayed using
the matches view assertion.
Notice that I didn't have to write any code in between
to wait for previous events to finish, as Espresso
already takes care of that for me.
To run the test, I right-click on the test class
and select Run.
Because it's an instrumentation test,
it requires an emulator or physical device.
I can see the actions on the screen as they execute.
Here's a slightly longer test that
includes typing into the add note screen and saving a note,
all using Espresso.
Unless you're writing end-to-end tests,
you should keep your tests small and scoped, which
will make them more reliable.
If you want to practice adding and running
UI tests on your own, I suggest you check out
our Android Testing Codelab, which I based this video on.
It contains a downloadable project
and step-by-step instructions to get you started.
Join me for the next episode of Android Testing
Patterns to learn how to handle adapter views in your tests.
Good luck, and happy testing.
[MUSIC PLAYING]