4

I've looking around for a while about espresso testing and specially about custom idling resources (I've implemented a couple working cases) but I have come across a scenario I can't seem to solve.

I have an Espresso SearchUITest class that starts an activity to search stuff. Before doing any search I open SettingsActivity to make some changes on the app configuration. When running pressBack() method from settings activity to get back to SearchActivity, a background task (not using AsyncTask) is started to update the configuration before going back to SearchActivity again.

The problem is SearchActivity is not resumed before the first call is done to interact with its UI. I'm getting this exception (sometimes I get the NoActivityResumedException and some others NoMatchingViewException):

android.support.test.espresso.NoActivityResumedException: No
activities in stage RESUMED. Did you forget to launch the activity.
(test.getActivity() or similar)? ...

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching:

How can I make Espresso wait for SettingsActivity to finish it's background task and open SearchActivity before running the next test sentence. I leave some code for further clarification (I'm running a parameterized test with espresso by the way):

@RunWith(value = Parameterized.class)
public class SearchByCountryE2ETest {

private static List<Country> mCountriesList;
private SearchActivity mActivity;

private String countryID;
private String countryLocation;
private String countryLanguage;

public SearchByCountryE2ETest(String countryID,
                              String countryLocation,
                              String language) {
    this.countryID = countryID;
    this.countryLocation = countryLocation;
    this.countryLanguage = language;
}


@Parameterized.Parameters(name = "id {0}, language{2}")
public static Collection countryIDs() {
    return Arrays.asList(new Object[][]{
            {"001", "mad", "Español (España)"},
            {"002", "lon", "English (United Kingdom)"}
    });
}

@Rule
public ActivityTestRule<SearchActivity> mSearchActivityRule = new ActivityTestRule<>(
        SearchActivity.class);

@Before
public void setUp() throws Exception {
    mSearchActivityRule.getActivity();
    if (mCountriesList == null) {
        mCountriesList = SingletonCommon.getInstance().getCountries().getCountry();
    }
}


@Test
public void testEnd2EndWithCountryID() {
    String countryName = getCountryNameById(countryID);
    if (countryName != null) {
        setCountryAndLanguage(countryName, countryLanguage);
        performCompleteSearch();
    }
}


private void setCountryAndLanguage(String countryName, String countryLanguage) {
    openSettings();
    changeLanguage(countryLanguage);
    changeCountry(countryName);
    pressBack();
    waitMillis(3000); // this is where the settings background task to update config is started
}

public void performCompleteSearch() {
    setLocation();
    clickViewWithId(R.id.search_button);//Go to filters activity

    onView(withId(R.id.search_button)).check(matches(isClickable()));//Check if results != 0
    clickViewWithId(R.id.search_button);//Go to listing activity

    waitMillis(1000); // wait millis is just a call to SystemClock.sleep(millis);

    openListingDetailAtPosition(1);// Click on item an open detail view
    pressBack();
}

private void openListingDetailAtPosition(int position) {
    onView(withId(R.id.recycler_view))
            .perform(scrollToPosition(position));
    onRecyclerViewItemAtPosition(click(), R.id.recycler_view, position);
}

private void openSettings() {
    onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
    onData(anything()).inAdapterView(withId(R.id.drawer_list_view)).atPosition(SETTINGS_DRAWER_POSITION).perform(click());
}

private void changeLanguage(String countryLanguage){
    if (countryLanguage != null && !countryLanguage.isEmpty()) {
        clickOnSpinnerStringItem(R.id.spinner_list_language, countryLanguage);
    }
}

private void changeCountry(String countryName){
    clickOnSpinnerStringItem(R.id.spinner_list_countries, countryName);
}

private void setLocation() {
    clickViewWithId(R.id.geolocation_edit_text);
    enterTextIntoViewWithId(countryLocation, R.id.location_edit_text);
    waitMillis(500);
    onRecyclerViewItemAtPosition(click(), R.id.locations_list, DEFAULT_SELECTED_LOCATION_POSITION);
    onView(withId(R.id.geolocation_edit_text)).perform(closeSoftKeyboard());
}

}

I have had to add waitMillis(millis) calls in order to wait for the app to finish loading background tasks for the activities opened from SearchActivity because I haven't been able to create and register idling resources for activities opened after the one that starts the test. I would also appreciate a lot if there is a complete example about how to do this (registering idling resources for different activities opened along the execution of the test).

If any further clarification is needed please tell me. Thanks in advance for any help.

JorgeMuci
  • 658
  • 9
  • 22
  • 1
    Hi, if problem still exists, please contact @chiuki, for example here: http://chiuki.github.io/ She is really expert in Espresso. Hope she help you – piotrek1543 Dec 30 '15 at 19:02
  • Thanks for the suggestion will do for sure! – JorgeMuci Jan 04 '16 at 08:22
  • 1
    Please include the code for `setCountryAndLanguage()` and `performCompleteSearch()`. – chiuki Jan 06 '16 at 18:08
  • 1
    Hi @chiuki I have edited the question adding the code missing. Thanks for the interest! – JorgeMuci Jan 07 '16 at 08:44
  • How do you run your background task? If you use `IntentService` you can use this technique: http://blog.sqisland.com/2015/04/espresso-custom-idling-resource.html – chiuki Jan 07 '16 at 16:48
  • Thanks for the reply @chiuki I have already seen that example before, in fact it really helped me to implement idling resource for other activities ui tests. The thing is I don't see how can I implement and register an idling resource for SettingsActivity, since the Actvity rule is set for SearchActivity which is the activity were the test starts and SettingsActivity is the opened during the test through a navigation drawer click. Is there any example on how to register an idling resource for different activity than the one set in the activity test rule?? – JorgeMuci Jan 08 '16 at 08:19
  • I don't use intent service by the way, I use regular threading for some network request using retrofit lib. – JorgeMuci Jan 08 '16 at 08:26
  • If you're using retrofit this maybe useful: http://stackoverflow.com/questions/23142437/how-to-test-android-ui-using-idlingresource-when-using-retrofit-network-requests/23450470#23450470 Make sure you have a view action at the end of `changeCountry` so Espresso knows to wait. – chiuki Jan 08 '16 at 16:16

0 Answers0