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