Testing for Android Intents Using Espresso
When developing applications for Android, it is important to be able to write tests to see if Intents fire or not. Previously, the concept of Intents created obstacles in testing. Android Espresso test support libraries provide ways to test parts of the application a lot more easily. There is an espresso-intents library specifically for testing Intents. With it you can test what Intents were fired on the device, and what extras they were sent with.
Setup
To start testing using Espresso, you first need to include the dependencies in your project. In addition to the basic Espresso setup, you need to add espresso-intents to your build.gradle
file.
// set up espresso
androidTestCompile 'com.android.support.test:runner:0.3'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
// include espresso-intents
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2'
In your test, you start by making a call to init()
from Intents. This will start recording the fired Intents, and is required before each test where you want to verify Intent activity.
For each time you call init()
, you must follow it up with a call to release()
at the end of the test. This will clear the Intents
state and stop recording intents.
Testing
Now that we are set up to start recording intents within a test, we can verify that the correct ones are being fired. In this case we want to test that the LoginActivity
is launched if there are no existing accounts. This way we can be sure that a user can’t access the app without having an account set up.
After the call to init()
, we set it up so there are no accounts, and used ActivityTestRule to start our activity. We chose to use ActivityTestRule over IntentsTestRule so we would have the choice to delay the starting of the activity. If you choose to use IntentsTestRule, keep in mind that it will automatically start your activity, and make the calls to init()
and release()
for you at the beginning and end of each test, respectively.
Intents.init();
AccountUtility.removeAccounts();
rule.launchActivity(new Intent());
We can next use intended()
with a Matcher
passed to it to assure that the Intent was fired, or not fired, as expected. IntentMatcher
’s hasComponent()
will return a Matcher that will match Intents with the given class name. This is one of multiple IntentMatchers that can be used.
intended(hasComponent(LoginActivity.class.getName()));
Intents.release();
Espresso-intents also gives us the ability to see if an intent launched x number of times. You can do this by including the number of times it should launch in the intended()
call. In our case, if there is already an account, the LoginActivity
should not be launched.
intended(hasComponent(MainActivity.class.getName()));
intended(hasComponent(LoginActivity.class.getName()), times(0));
Full code is available here.
Conclusion
Espresso-intents is a useful tool when creating tests for your Android application. To complement your tests confined to a single activity at a time, you can test the flow of your activities and test when Intents are fired. In addition to everything we’ve done here, Espresso also allows us to stub Intents, and test for their extras. Adopting this practice of testing Intents into your Android tests should help you to create a more complete test suite for your application.
Comments
Google recently released a long-awaited new version of Espresso (known as v2.0 now). Even the first version sparked some noticeable interest among test automation community, it seems that the second version is a great improvement and should be definitely checked out by everyone who uses Espresso as their test automation framework.