1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
/*
* 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.
*
* <p>Other options supported by this test case include:
* <ul>
* <li>You can run any test method on the UI thread (see {@link android.test.UiThreadTest}).</li>
* <li>You can inject custom Intents into your Activity (see
* {@link #setActivityIntent(Intent)}).</li>
* </ul>
*
* <p>This class replaces {@link android.test.ActivityInstrumentationTestCase}, which is deprecated.
* New tests should be written using this base class.
*
* <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
*/
public abstract class ActivityInstrumentationTestCase2<T extends Activity>
extends ActivityTestCase {
Class<T> 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<T> 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<T> 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.
*
* <p>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.
*
* <p><b>NOTE:</b> 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.
*
* <p>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.
*
* <p><b>NOTE:</b> 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()}.
*
* <p>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.
*
* <p>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.
*
* <p><b>NOTE:</b> 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();
boolean mInitialTouchMode = false;
Intent 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();
}
}
|