Updated #1: more info added to the end of this post
I\'m new to Android development and testing.
I have three Espresso tests. First test passes, but the
I found a workaround. I added code that hits back button multiple times in the tearDown() method to close all previously opened activities. Unfortunately I didn't found another method how to close all opened activities in Espresso. Robotium has a very convenient method for that purpose solo.finishOpenedActivities().
public void tearDown() throws Exception {
Log.d(TAG, "TEARDOWN");
goBackN();
super.tearDown();
}
private void goBackN() {
final int N = 10; // how many times to hit back button
try {
for (int i = 0; i < N; i++)
Espresso.pressBack();
} catch (com.google.android.apps.common.testing.ui.espresso.NoActivityResumedException e) {
Log.e(TAG, "Closed all activities", e);
}
}
pressBack solution does not worked for me but I found another:
@Override
protected void tearDown() throws Exception {
closeAllActivities(getInstrumentation());
super.tearDown();
}
public static void closeAllActivities(Instrumentation instrumentation) throws Exception {
final int NUMBER_OF_RETRIES = 100;
int i = 0;
while (closeActivity(instrumentation)) {
if (i++ > NUMBER_OF_RETRIES) {
throw new AssertionError("Limit of retries excesses");
}
Thread.sleep(200);
}
}
public static <X> X callOnMainSync(Instrumentation instrumentation, final Callable<X> callable) throws Exception {
final AtomicReference<X> retAtomic = new AtomicReference<>();
final AtomicReference<Throwable> exceptionAtomic = new AtomicReference<>();
instrumentation.runOnMainSync(new Runnable() {
@Override
public void run() {
try {
retAtomic.set(callable.call());
} catch (Throwable e) {
exceptionAtomic.set(e);
}
}
});
final Throwable exception = exceptionAtomic.get();
if (exception != null) {
Throwables.propagateIfInstanceOf(exception, Exception.class);
Throwables.propagate(exception);
}
return retAtomic.get();
}
public static Set<Activity> getActivitiesInStages(Stage... stages) {
final Set<Activity> activities = Sets.newHashSet();
final ActivityLifecycleMonitor instance = ActivityLifecycleMonitorRegistry.getInstance();
for (Stage stage : stages) {
final Collection<Activity> activitiesInStage = instance.getActivitiesInStage(stage);
if (activitiesInStage != null) {
activities.addAll(activitiesInStage);
}
}
return activities;
}
private static boolean closeActivity(Instrumentation instrumentation) throws Exception {
final Boolean activityClosed = callOnMainSync(instrumentation, new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
final Set<Activity> activities = getActivitiesInStages(Stage.RESUMED,
Stage.STARTED, Stage.PAUSED, Stage.STOPPED, Stage.CREATED);
activities.removeAll(getActivitiesInStages(Stage.DESTROYED));
if (activities.size() > 0) {
final Activity activity = activities.iterator().next();
activity.finish();
return true;
} else {
return false;
}
}
});
if (activityClosed) {
instrumentation.waitForIdleSync();
}
return activityClosed;
}
Try the following:
@Before
public void setUp() throws Exception {
super.setUp();
Log.d(TAG, "SETUP");
activity = getActivity();
}
This seems to work for me to close all of the activities in the stack except the first one.
@After
@Override
public void tearDown() throws Exception
{
Intent intent = new Intent(getActivity(), getActivity().getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Removes other Activities from stack
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
myActivity.startActivity(intent);
super.tearDown();
}