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.