How to test a specific Activity with Espresso?

Moses picture Moses · Jul 25, 2016 · Viewed 11.5k times · Source

I have only just started with testing in Android and this seems very basic but after much googling I still can't find the answer anywhere.

In my Android app the first activity which is displayed is a login screen, followed by a home screen with options to navigate to other activities. In order to test the activity I want I currently have to move through these two activities first.

How do I setup the Espresso test (using ActvityTestRule/JUnit4) so that it launches the activity I want to test straight away?

EDIT

More specifically, my issue is that in all tutorials I have seen for Espresso tests all tests start off at the main activity of the application with an ActivityTestRule that looks like this

@Rule
public final ActivityTestRule<MainActivity> mRule = new ActivityTestRule<MainActivity>(MainActivity.class);

I want the tests to start at a specified activity, which currently I am having navigate to by constantly repeating test code like this

onView(withId(R.id.go_to_other_activity_button)).perform(click())

Answer

originx picture originx · Aug 5, 2016

If you want to run specific activity then: ActivityTestRule or IntentTestRule is what you need.

The contract is pretty self explanatory just set your desired activity that you want to start as first parameter.

ActivityTestRule<>(ActivityYouWantToStart.class, initialTouchMode, launchActivity) //rule for activity start


IntentTestRule<>(ActivityYouWantToStart.class, initialTouchMode, launchActivity) //used for testing intents and activities

Important to notice here is launchActivity boolean. If you set this to true each test will automatically launch the activity.

Other usage for it is if some activities expect some intent, data or similar to be sent to it before running them you can set this parameter to false and prepare your app before running the test / activity.

For example if you need a logged in user saved in your shared preferences to run Activity B and logic of that activity says:

if(!userIsLoggedIn()){

    jumpToMainActivity();

}

Then you can save some mock user before running that test or for example fill the database with mock objects and after you prepare your environment for Activity B everything then you call.

mActivityRule.launchActivity(null);

Notice that launchActivity takes a parameter, this is actually Intent that Activity B receives, if it expects some extra data in that way you can prepare the Intent before starting the test.

Full example of running custom activity:

/**
* Testing of the snackbar activity.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
    //espresso rule which tells which activity to start
    @Rule
    public final ActivityTestRule<SnackbarActivity> mActivityRule = 
        new ActivityTestRule<>(SnackbarActivity.class, true, false);


    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        //just an example how tear down should cleanup after itself
        mDatabase.clear();
        mSharedPrefs.clear();
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        //setting up your application, for example if you need to have a user in shared
        //preferences to stay logged in you can do that for all tests in your setup
        User mUser = new User();
        mUser.setToken("randomToken");
    }

    /**
    *Test methods should always start with "testXYZ" and it is a good idea to 
    *name them after the intent what you want to test
    **/
    @Test
    public void testSnackbarIsShown() {
        //start our activity
        mActivityRule.launchActivity(null);
        //check is our text entry displayed and enter some text to it
        String textToType="new snackbar text";
        onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
        onView(withId(R.id.textEntry)).perform(typeText(textToType));
        //click the button to show the snackbar
        onView(withId(R.id.shownSnackbarBtn)).perform(click());
        //assert that a view with snackbar_id with text which we typed and is displayed
        onView(allOf(withId(android.support.design.R.id.snackbar_text), 
        withText(textToType))) .check(matches(isDisplayed()));
    }
}