Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso functional tests with fragments

I have three activities in my app

  1. A login activity
  2. A main activity
  3. A detail activity

I want to use espresso to test a sequence of events: click the login button on the login activity, which opens the main activity, and then click a list item in main activity, which opens detail activity, and then click another button in the detail activity. I started by creating this simple test, to get a reference to the listview:

public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {

    public LoginActivityTest() {
        super(LoginActivity.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();

        getActivity();
    }

    public void testSequence() throws Exception {
        // Login
        onView(withId(R.id.button_log_in)).perform(click());

        // Check if MainActivity is loaded
        onView(withId(R.id.container)).check(matches(isDisplayed()));

        // Check if Fragment is loaded
        onView(withId(R.id.list)).check(matches(isDisplayed()));
    }
}

On the mainActivity onCreate() method I load a fragment like this:

getFragmentManager().beginTransaction()
                .add(R.id.container, mListFragment)
                .commit();

The ListFragment fragment has a list (R.id.list), but still the test fails with a NoMatchingViewException:

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.tests.android.development:id/list

What am I doing wrong?

like image 856
Filipe Ramos Avatar asked Feb 11 '15 13:02

Filipe Ramos


1 Answers

A note from the documentation for onView:

Note: the view has to be part of the view hierarchy. This may not be the case if it is rendered as part of an AdapterView (e.g. ListView). If this is the case, use Espresso.onData to load the view first.

To use onData to load the view, you need to check for instances of whatever your adapter is in the ListView. In other words, if your listview uses a Cursor adapter, you can try this:

onData(allOf(is(instanceOf(Cursor.class)))).check(matches(isDisplayed()));

It is important to note that the above will only pass if your listview contains at least one item. It is a good idea to have one test where an item exists, and one test where an item does not.

For more information on how to check for data that does exist, see here.

For more information on how to check for data that does not exist in an adapter, see here.

like image 98
AdamMc331 Avatar answered Oct 05 '22 23:10

AdamMc331