Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bootstraponline/ce2ce790008980fc1f04d33b9baba7d7 to your computer and use it in GitHub Desktop.
Save bootstraponline/ce2ce790008980fc1f04d33b9baba7d7 to your computer and use it in GitHub Desktop.
Android Espresso Activity Clean Up
/**
* Copyright (C) 2017 Drew Hannay
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.test.rule;
import android.app.Activity;
import android.support.test.runner.MonitoringInstrumentationAccessor;
import android.util.Log;
import java.lang.reflect.Field;
/**
* Subclass of {@link ActivityTestRule} that cleanly handles finishing multiple activities.
* <p/>
* The official ActivityTestRule only calls finish() on the initial activity. However, this can cause problems if the
* test ends in a different activity than which it was started. In this implementation, we call finish() on all
* Activity classes that are started and wait until they actually finish before proceeding.
*/
public class FinishingActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
private static final String TAG = FinishingActivityTestRule.class.getSimpleName();
public FinishingActivityTestRule(Class<T> activityClass) {
super(activityClass);
}
public FinishingActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
super(activityClass, initialTouchMode);
}
public FinishingActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
super(activityClass, initialTouchMode, launchActivity);
}
@Override
void finishActivity() {
MonitoringInstrumentationAccessor.finishAllActivities();
// purposefully don't call super since we've already finished all the activities
// instead, null out the mActivity field in the parent class using reflection
try {
Field activityField = ActivityTestRule.class.getDeclaredField("mActivity");
activityField.setAccessible(true);
activityField.set(this, null);
} catch (NoSuchFieldException e) {
Log.e(TAG, "Unable to get field through reflection", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "Unable to get access field through reflection", e);
}
}
}
/**
* Copyright (C) 2017 Drew Hannay
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.test.runner;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.util.Log;
/**
* Helper class for calling protected methods in MonitoringInstrumentation
*/
public class MonitoringInstrumentationAccessor {
private static final String TAG = MonitoringInstrumentationAccessor.class.getSimpleName();
private static final Handler HANDLER_FOR_MAIN_LOOPER = new Handler(Looper.getMainLooper());
private MonitoringInstrumentationAccessor() {}
/**
* Synchronously finish all currently started activities
*/
public static void finishAllActivities() {
MonitoringInstrumentation instrumentation = (MonitoringInstrumentation) InstrumentationRegistry.getInstrumentation();
MonitoringInstrumentation.ActivityFinisher activityFinisher = instrumentation.new ActivityFinisher();
HANDLER_FOR_MAIN_LOOPER.post(activityFinisher);
long startTime = System.currentTimeMillis();
instrumentation.waitForActivitiesToComplete();
long endTime = System.currentTimeMillis();
Log.i(TAG, String.format("waitForActivitiesToComplete() took: %sms", endTime - startTime));
}
}
@CyxouD
Copy link

CyxouD commented Mar 29, 2018

It's better to mention that you should create packages android.support.test.runner and android.support.test.rule in your src/androidTest/java or src/androidTest/kotlin folder or you won't be able to access waitForActivitiesToComplete() method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment