blob: 679f6346537b94e05eafb302992f6472ec22fb87 [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 {
43 String mPackage;
44 Class<T> mActivityClass;
45 boolean mInitialTouchMode = false;
46 Intent mActivityIntent = null;
47
48 /**
Andy Stadler72d5de72009-04-21 11:54:14 -070049 * <b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
50 * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
51 * file. This is not necessarily the same as the java package name.
52 *
53 * @param pkg The package hosting the activity to be launched.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 * @param activityClass The activity to test.
55 */
56 public ActivityInstrumentationTestCase2(String pkg, Class<T> activityClass) {
57 mPackage = pkg;
58 mActivityClass = activityClass;
59 }
60
61 /**
62 * Get the Activity under test, starting it if necessary.
63 *
64 * For each test method invocation, the Activity will not actually be created until the first
65 * time this method is called.
66 *
67 * <p>If you wish to provide custom setup values to your Activity, you may call
68 * {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)}
69 * before your first call to getActivity(). Calling them after your Activity has
70 * started will have no effect.
71 *
72 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
73 * If your test method is annotated with {@link android.test.UiThreadTest}, then your Activity
74 * will be started automatically just before your test method is run. You still call this
75 * method in order to get the Activity under test.
76 *
77 * @return the Activity under test
78 */
79 @Override
80 public T getActivity() {
81 Activity a = super.getActivity();
82 if (a == null) {
83 // set initial touch mode
84 getInstrumentation().setInTouchMode(mInitialTouchMode);
85 // inject custom intent, if provided
86 if (mActivityIntent == null) {
87 a = launchActivity(mPackage, mActivityClass, null);
88 } else {
89 a = launchActivityWithIntent(mPackage, mActivityClass, mActivityIntent);
90 }
91 setActivity(a);
92 }
93 return (T) a;
94 }
95
96 /**
97 * Call this method before the first call to {@link #getActivity} to inject a customized Intent
98 * into the Activity under test.
99 *
100 * <p>If you do not call this, the default intent will be provided. If you call this after
101 * your Activity has been started, it will have no effect.
102 *
103 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
104 * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
105 * {@link #setActivityIntent(Intent)} from {@link #setUp()}.
106 *
107 * <p>The default Intent (if this method is not called) is:
108 * action = {@link Intent#ACTION_MAIN}
109 * flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
110 * All other fields are null or empty.
111 *
112 * @param i The Intent to start the Activity with, or null to reset to the default Intent.
113 */
114 public void setActivityIntent(Intent i) {
115 mActivityIntent = i;
116 }
117
118 /**
119 * Call this method before the first call to {@link #getActivity} to set the initial touch
120 * mode for the Activity under test.
121 *
122 * <p>If you do not call this, the touch mode will be false. If you call this after
123 * your Activity has been started, it will have no effect.
124 *
125 * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
126 * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
127 * {@link #setActivityInitialTouchMode(boolean)} from {@link #setUp()}.
128 *
129 * @param initialTouchMode true if the Activity should be placed into "touch mode" when started
130 */
131 public void setActivityInitialTouchMode(boolean initialTouchMode) {
132 mInitialTouchMode = initialTouchMode;
133 }
134
135 @Override
136 protected void setUp() throws Exception {
137 super.setUp();
138
139 boolean mInitialTouchMode = false;
140 Intent mActivityIntent = null;
141 }
142
143 @Override
144 protected void tearDown() throws Exception {
145 // Finish the Activity off (unless was never launched anyway)
146 Activity a = super.getActivity();
147 if (a != null) {
148 a.finish();
149 setActivity(null);
150 }
151
152 // Scrub out members - protects against memory leaks in the case where someone
153 // creates a non-static inner class (thus referencing the test case) and gives it to
154 // someone else to hold onto
155 scrubClass(ActivityInstrumentationTestCase2.class);
156
157 super.tearDown();
158 }
159
160 /**
161 * Runs the current unit test. If the unit test is annotated with
162 * {@link android.test.UiThreadTest}, force the Activity to be created before switching to
163 * the UI thread.
164 */
165 @Override
166 protected void runTest() throws Throwable {
167 try {
168 Method method = getClass().getMethod(getName(), (Class[]) null);
169 if (method.isAnnotationPresent(UiThreadTest.class)) {
170 getActivity();
171 }
172 } catch (Exception e) {
173 // eat the exception here; super.runTest() will catch it again and handle it properly
174 }
175 super.runTest();
176 }
177
178}