blob: e8570bd80f1de9497c5ff2a41fbf0f1af8687b38 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.test;
18
19import android.app.Activity;
20import android.content.Intent;
21
22import java.lang.reflect.Method;
23
24/**
25 * This class provides functional testing of a single activity. The activity under test will
26 * be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity())
27 * and you will then be able to manipulate your Activity directly.
28 *
29 * <p>Other options supported by this test case include:
30 * <ul>
31 * <li>You can run any test method on the UI thread (see {@link android.test.UiThreadTest}).</li>
32 * <li>You can inject custom Intents into your Activity (see
33 * {@link #setActivityIntent(Intent)}).</li>
34 * </ul>
35 *
36 * <p>This class replaces {@link android.test.ActivityInstrumentationTestCase}, which is deprecated.
37 * New tests should be written using this base class.
38 *
39 * <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
40 */
41public abstract class ActivityInstrumentationTestCase2<T extends Activity>
42 extends ActivityTestCase {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043 Class<T> mActivityClass;
44 boolean mInitialTouchMode = false;
45 Intent mActivityIntent = null;
46
47 /**
Brett Chabot90762d32010-02-11 20:07:17 -080048 * Creates an {@link ActivityInstrumentationTestCase2}.
49 *
50 * @param pkg ignored - no longer in use.
51 * @param activityClass The activity to test. This must be a class in the instrumentation
52 * targetPackage specified in the AndroidManifest.xml
53 *
54 * @deprecated use {@link #ActivityInstrumentationTestCase2(Class)} instead
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 */
Brett Chabot90762d32010-02-11 20:07:17 -080056 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 public ActivityInstrumentationTestCase2(String pkg, Class<T> activityClass) {
Brett Chabot90762d32010-02-11 20:07:17 -080058 this(activityClass);
59 }
60
61 /**
62 * Creates an {@link ActivityInstrumentationTestCase2}.
63 *
64 * @param activityClass The activity to test. This must be a class in the instrumentation
65 * targetPackage specified in the AndroidManifest.xml
66 */
67 public ActivityInstrumentationTestCase2(Class<T> activityClass) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 mActivityClass = activityClass;
69 }
70
71 /**
72 * Get the Activity under test, starting it if necessary.
73 *
74 * For each test method invocation, the Activity will not actually be created until the first
75 * time this method is called.
76 *
77 * <p>If you wish to provide custom setup values to your Activity, you may call
78 * {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)}
79 * before your first call to getActivity(). Calling them after your Activity has
80 * started will have no effect.
81 *
82 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
83 * If your test method is annotated with {@link android.test.UiThreadTest}, then your Activity
84 * will be started automatically just before your test method is run. You still call this
85 * method in order to get the Activity under test.
86 *
87 * @return the Activity under test
88 */
89 @Override
90 public T getActivity() {
91 Activity a = super.getActivity();
92 if (a == null) {
93 // set initial touch mode
94 getInstrumentation().setInTouchMode(mInitialTouchMode);
Brett Chabot90762d32010-02-11 20:07:17 -080095 final String targetPackage = getInstrumentation().getTargetContext().getPackageName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 // inject custom intent, if provided
97 if (mActivityIntent == null) {
Brett Chabot90762d32010-02-11 20:07:17 -080098 a = launchActivity(targetPackage, mActivityClass, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 } else {
Brett Chabot90762d32010-02-11 20:07:17 -0800100 a = launchActivityWithIntent(targetPackage, mActivityClass, mActivityIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 }
102 setActivity(a);
103 }
104 return (T) a;
105 }
106
107 /**
108 * Call this method before the first call to {@link #getActivity} to inject a customized Intent
109 * into the Activity under test.
110 *
111 * <p>If you do not call this, the default intent will be provided. If you call this after
112 * your Activity has been started, it will have no effect.
113 *
114 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
115 * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
116 * {@link #setActivityIntent(Intent)} from {@link #setUp()}.
117 *
118 * <p>The default Intent (if this method is not called) is:
119 * action = {@link Intent#ACTION_MAIN}
120 * flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
121 * All other fields are null or empty.
122 *
123 * @param i The Intent to start the Activity with, or null to reset to the default Intent.
124 */
125 public void setActivityIntent(Intent i) {
126 mActivityIntent = i;
127 }
128
129 /**
130 * Call this method before the first call to {@link #getActivity} to set the initial touch
131 * mode for the Activity under test.
132 *
133 * <p>If you do not call this, the touch mode will be false. If you call this after
134 * your Activity has been started, it will have no effect.
135 *
136 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
137 * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
138 * {@link #setActivityInitialTouchMode(boolean)} from {@link #setUp()}.
139 *
140 * @param initialTouchMode true if the Activity should be placed into "touch mode" when started
141 */
142 public void setActivityInitialTouchMode(boolean initialTouchMode) {
143 mInitialTouchMode = initialTouchMode;
144 }
145
146 @Override
147 protected void setUp() throws Exception {
148 super.setUp();
149
150 boolean mInitialTouchMode = false;
151 Intent mActivityIntent = null;
152 }
153
154 @Override
155 protected void tearDown() throws Exception {
156 // Finish the Activity off (unless was never launched anyway)
157 Activity a = super.getActivity();
158 if (a != null) {
159 a.finish();
160 setActivity(null);
161 }
162
163 // Scrub out members - protects against memory leaks in the case where someone
164 // creates a non-static inner class (thus referencing the test case) and gives it to
165 // someone else to hold onto
166 scrubClass(ActivityInstrumentationTestCase2.class);
167
168 super.tearDown();
169 }
170
171 /**
172 * Runs the current unit test. If the unit test is annotated with
173 * {@link android.test.UiThreadTest}, force the Activity to be created before switching to
174 * the UI thread.
175 */
176 @Override
177 protected void runTest() throws Throwable {
178 try {
179 Method method = getClass().getMethod(getName(), (Class[]) null);
180 if (method.isAnnotationPresent(UiThreadTest.class)) {
181 getActivity();
182 }
183 } catch (Exception e) {
184 // eat the exception here; super.runTest() will catch it again and handle it properly
185 }
186 super.runTest();
187 }
188
189}