/* * Copyright (C) 2008 The Android Open Source Project * * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.test; import android.app.Activity; import android.content.Intent; import java.lang.reflect.Method; /** * This class provides functional testing of a single activity. The activity under test will * be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity()) * and you will then be able to manipulate your Activity directly. * *

Other options supported by this test case include: *

* *

This class replaces {@link android.test.ActivityInstrumentationTestCase}, which is deprecated. * New tests should be written using this base class. * *

If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}. * *

*

Developer Guides

*

For more information about application testing, read the * Testing developer guide.

*
*/ public abstract class ActivityInstrumentationTestCase2 extends ActivityTestCase { Class mActivityClass; boolean mInitialTouchMode = false; Intent mActivityIntent = null; /** * Creates an {@link ActivityInstrumentationTestCase2}. * * @param pkg ignored - no longer in use. * @param activityClass The activity to test. This must be a class in the instrumentation * targetPackage specified in the AndroidManifest.xml * * @deprecated use {@link #ActivityInstrumentationTestCase2(Class)} instead */ @Deprecated public ActivityInstrumentationTestCase2(String pkg, Class activityClass) { this(activityClass); } /** * Creates an {@link ActivityInstrumentationTestCase2}. * * @param activityClass The activity to test. This must be a class in the instrumentation * targetPackage specified in the AndroidManifest.xml */ public ActivityInstrumentationTestCase2(Class activityClass) { mActivityClass = activityClass; } /** * Get the Activity under test, starting it if necessary. * * For each test method invocation, the Activity will not actually be created until the first * time this method is called. * *

If you wish to provide custom setup values to your Activity, you may call * {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)} * before your first call to getActivity(). Calling them after your Activity has * started will have no effect. * *

NOTE: Activities under test may not be started from within the UI thread. * If your test method is annotated with {@link android.test.UiThreadTest}, then your Activity * will be started automatically just before your test method is run. You still call this * method in order to get the Activity under test. * * @return the Activity under test */ @Override public T getActivity() { Activity a = super.getActivity(); if (a == null) { // set initial touch mode getInstrumentation().setInTouchMode(mInitialTouchMode); final String targetPackage = getInstrumentation().getTargetContext().getPackageName(); // inject custom intent, if provided if (mActivityIntent == null) { a = launchActivity(targetPackage, mActivityClass, null); } else { a = launchActivityWithIntent(targetPackage, mActivityClass, mActivityIntent); } setActivity(a); } return (T) a; } /** * Call this method before the first call to {@link #getActivity} to inject a customized Intent * into the Activity under test. * *

If you do not call this, the default intent will be provided. If you call this after * your Activity has been started, it will have no effect. * *

NOTE: Activities under test may not be started from within the UI thread. * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call * {@link #setActivityIntent(Intent)} from {@link #setUp()}. * *

The default Intent (if this method is not called) is: * action = {@link Intent#ACTION_MAIN} * flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK} * All other fields are null or empty. * * @param i The Intent to start the Activity with, or null to reset to the default Intent. */ public void setActivityIntent(Intent i) { mActivityIntent = i; } /** * Call this method before the first call to {@link #getActivity} to set the initial touch * mode for the Activity under test. * *

If you do not call this, the touch mode will be false. If you call this after * your Activity has been started, it will have no effect. * *

NOTE: Activities under test may not be started from within the UI thread. * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call * {@link #setActivityInitialTouchMode(boolean)} from {@link #setUp()}. * * @param initialTouchMode true if the Activity should be placed into "touch mode" when started */ public void setActivityInitialTouchMode(boolean initialTouchMode) { mInitialTouchMode = initialTouchMode; } @Override protected void setUp() throws Exception { super.setUp(); mInitialTouchMode = false; mActivityIntent = null; } @Override protected void tearDown() throws Exception { // Finish the Activity off (unless was never launched anyway) Activity a = super.getActivity(); if (a != null) { a.finish(); setActivity(null); } // Scrub out members - protects against memory leaks in the case where someone // creates a non-static inner class (thus referencing the test case) and gives it to // someone else to hold onto scrubClass(ActivityInstrumentationTestCase2.class); super.tearDown(); } /** * Runs the current unit test. If the unit test is annotated with * {@link android.test.UiThreadTest}, force the Activity to be created before switching to * the UI thread. */ @Override protected void runTest() throws Throwable { try { Method method = getClass().getMethod(getName(), (Class[]) null); if (method.isAnnotationPresent(UiThreadTest.class)) { getActivity(); } } catch (Exception e) { // eat the exception here; super.runTest() will catch it again and handle it properly } super.runTest(); } }