• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Activity Testing
2parent.title=Testing
3parent.link=index.html
4@jd:body
5
6<div id="qv-wrapper">
7  <div id="qv">
8  <h2>In this document</h2>
9  <ol>
10    <li>
11      <a href="#ActivityTestAPI">The Activity Testing API</a>
12      <ol>
13        <li>
14            <a href="#ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</a>
15        </li>
16        <li>
17            <a href="#ActivityUnitTestCase">ActivityUnitTestCase</a>
18        </li>
19        <li>
20            <a href="#SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</a>
21        </li>
22        <li>
23            <a href="#MockObjectNotes">Mock objects and activity testing</a>
24        </li>
25        <li>
26            <a href="#AssertionNotes">Assertions for activity testing</a>
27        </li>
28      </ol>
29    </li>
30    <li>
31        <a href="#WhatToTest">What to Test</a>
32    </li>
33    <li>
34        <a href="#NextSteps">Next Steps</a>
35    </li>
36    <li>
37      <a href="#UITesting">Appendix: UI Testing Notes</a>
38      <ol>
39        <li>
40          <a href="#RunOnUIThread">Testing on the UI thread</a>
41        </li>
42        <li>
43          <a href="#NotouchMode">Turning off touch mode</a>
44        </li>
45        <li>
46          <a href="#UnlockDevice">Unlocking the Emulator or Device</a>
47        </li>
48        <li>
49          <a href="#UITestTroubleshooting">Troubleshooting UI tests</a>
50        </li>
51      </ol>
52    </li>
53    </ol>
54<h2>Key Classes</h2>
55    <ol>
56      <li>{@link android.test.InstrumentationTestRunner}</li>
57      <li>{@link android.test.ActivityInstrumentationTestCase2}</li>
58      <li>{@link android.test.ActivityUnitTestCase}</li>
59    </ol>
60<h2>Related Tutorials</h2>
61    <ol>
62      <li>
63        <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
64        Hello, Testing</a>
65      </li>
66      <li>
67         <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
68      </li>
69    </ol>
70<h2>See Also</h2>
71      <ol>
72        <li>
73          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
74          Testing in Eclipse, with ADT</a>
75        </li>
76        <li>
77          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
78          Testing in Other IDEs</a>
79        </li>
80      </ol>
81  </div>
82</div>
83<p>
84    Activity testing is particularly dependent on the the Android instrumentation framework.
85    Unlike other components, activities have a complex lifecycle based on callback methods; these
86    can't be invoked directly except by instrumentation. Also, the only way to send events to the
87    user interface from a program is through instrumentation.
88</p>
89<p>
90    This document describes how to test activities using instrumentation and other test
91    facilities. The document assumes you have already read
92    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
93    the introduction to the Android testing and instrumentation framework.
94</p>
95<h2 id="ActivityTestAPI">The Activity Testing API</h2>
96<p>
97    The activity testing API base class is {@link android.test.InstrumentationTestCase},
98    which provides instrumentation to the test case subclasses you use for Activities.
99</p>
100<p>
101    For activity testing, this base class provides these functions:
102</p>
103<ul>
104    <li>
105        Lifecycle control: With instrumentation, you can start the activity under test, pause it,
106        and destroy it, using methods provided by the test case classes.
107    </li>
108    <li>
109        Dependency injection: Instrumentation allows you to create mock system objects such as
110        Contexts or Applications and use them to run the activity under test. This
111        helps you control the test environment and isolate it from production systems. You can
112        also set up customized Intents and start an activity with them.
113    </li>
114    <li>
115        User interface interaction: You use instrumentation to send keystrokes or touch events
116        directly to the UI of the activity under test.
117    </li>
118</ul>
119<p>
120    The activity testing classes also provide the JUnit framework by extending
121    {@link junit.framework.TestCase} and {@link junit.framework.Assert}.
122</p>
123<p>
124    The two main testing subclasses are {@link android.test.ActivityInstrumentationTestCase2} and
125    {@link android.test.ActivityUnitTestCase}. To test an Activity that is launched in a mode
126    other than <code>standard</code>, you use {@link android.test.SingleLaunchActivityTestCase}.
127</p>
128<h3 id="ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</h3>
129<p>
130    The {@link android.test.ActivityInstrumentationTestCase2} test case class is designed to do
131    functional testing of one or more Activities in an application, using a normal system
132    infrastructure. It runs the Activities in a normal instance of the application under test,
133    using a standard system Context. It allows you to send mock Intents to the activity under
134    test, so you can use it to test an activity that responds to multiple types of intents, or
135    an activity that expects a certain type of data in the intent, or both. Notice, though, that it
136    does not allow mock Contexts or Applications, so you can not isolate the test from the rest of
137    a production system.
138</p>
139<h3 id="ActivityUnitTestCase">ActivityUnitTestCase</h3>
140<p>
141    The {@link android.test.ActivityUnitTestCase} test case class tests a single activity in
142    isolation. Before you start the activity, you can inject a mock Context or Application, or both.
143    You use it to run activity tests in isolation, and to do unit testing of methods
144    that do not interact with Android. You can not send mock Intents to the activity under test,
145    although you can call
146    {@link android.app.Activity#startActivity(Intent) Activity.startActivity(Intent)} and then
147    look at arguments that were received.
148</p>
149<h3 id="SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</h3>
150<p>
151    The {@link android.test.SingleLaunchActivityTestCase} class is a convenience class for
152    testing a single activity in an environment that doesn't change from test to test.
153    It invokes {@link junit.framework.TestCase#setUp() setUp()} and
154    {@link junit.framework.TestCase#tearDown() tearDown()} only once, instead of once per
155    method call. It does not allow you to inject any mock objects.
156</p>
157<p>
158    This test case is useful for testing an activity that runs in a mode other than
159    <code>standard</code>. It ensures that the test fixture is not reset between tests. You
160    can then test that the activity handles multiple calls correctly.
161</p>
162<h3 id="MockObjectNotes">Mock objects and activity testing</h3>
163<p>
164    This section contains notes about the use of the mock objects defined in
165    {@link android.test.mock} with activity tests.
166</p>
167<p>
168    The mock object {@link android.test.mock.MockApplication} is only available for activity
169    testing if you use the {@link android.test.ActivityUnitTestCase} test case class.
170    By default, <code>ActivityUnitTestCase</code>, creates a hidden <code>MockApplication</code>
171    object that is used as the application under test. You can inject your own object using
172    {@link android.test.ActivityUnitTestCase#setApplication(Application) setApplication()}.
173</p>
174<h3 id="AssertionNotes">Assertions for activity testing</h3>
175<p>
176    {@link android.test.ViewAsserts} defines assertions for Views. You use it to verify the
177    alignment and position of View objects, and to look at the state of ViewGroup objects.
178</p>
179<h2 id="WhatToTest">What To Test</h2>
180<ul>
181    <li>
182        Input validation: Test that an activity responds correctly to input values in an
183        EditText View. Set up a keystroke sequence, send it to the activity, and then
184        use {@link android.view.View#findViewById(int)} to examine the state of the View. You can
185        verify that a valid keystroke sequence enables an OK button, while an invalid one leaves the
186        button disabled. You can also verify that the Activity responds to invalid input by
187        setting error messages in the View.
188    </li>
189    <li>
190        Lifecycle events: Test that each of your application's activities handles lifecycle events
191        correctly. In general, lifecycle events are actions, either from the system or from the
192        user, that trigger a callback method such as <code>onCreate()</code> or
193        <code>onClick()</code>. For example, an activity should respond to pause or destroy events
194        by saving its state. Remember that even a change in screen orientation causes the current
195        activity to be destroyed, so you should test that accidental device movements don't
196        accidentally lose the application state.
197    </li>
198    <li>
199        Intents: Test that each activity correctly handles the intents listed in the intent
200        filter specified in its manifest. You can use
201        {@link android.test.ActivityInstrumentationTestCase2} to send mock Intents to the
202        activity under test.
203    </li>
204    <li>
205        Runtime configuration changes: Test that each activity responds correctly to the
206        possible changes in the device's configuration while your application is running. These
207        include a change to the device's orientation, a change to the current language, and so
208        forth. Handling these changes is described in detail in the topic
209        <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime
210        Changes</a>.
211    </li>
212    <li>
213        Screen sizes and resolutions: Before you publish your application, make sure to test it on
214        all of the screen sizes and densities on which you want it to run. You can test the
215        application on multiple sizes and densities using AVDs, or you can test your application
216        directly on the devices that you are targeting. For more information, see the topic
217        <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.
218    </li>
219</ul>
220<h2 id="NextSteps">Next Steps</h2>
221<p>
222    To learn how to set up and run tests in Eclipse, please refer to <a
223    href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
224    Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
225    href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
226    IDEs</a>.
227</p>
228<p>
229    If you want a step-by-step introduction to testing activities, try one of the
230    testing tutorials:
231</p>
232<ul>
233    <li>
234        The <a
235        href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
236        Testing</a> tutorial introduces basic testing concepts and procedures in the
237        context of the Hello, World application.
238    </li>
239    <li>
240        The <a
241        href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
242        Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
243        It guides you through a more complex testing scenario that you develop against a
244        more realistic activity-oriented application.
245    </li>
246</ul>
247<h2 id="UITesting">Appendix: UI Testing Notes</h2>
248<p>
249    The following sections have tips for testing the UI of your Android application, specifically
250    to help you handle actions that run in the UI thread, touch screen and keyboard events, and home
251    screen unlock during testing.
252</p>
253<h3 id="RunOnUIThread">Testing on the UI thread</h3>
254<p>
255    An application's activities run on the application's <strong>UI thread</strong>. Once the
256    UI is instantiated, for example in the activity's <code>onCreate()</code> method, then all
257    interactions with the UI must run in the UI thread. When you run the application normally, it
258    has access to the thread and does not have to do anything special.
259</p>
260<p>
261    This changes when you run tests against the application. With instrumentation-based classes,
262    you can invoke methods against the UI of the application under test. The other test classes
263    don't allow this. To run an entire test method on the UI thread, you can annotate the thread
264    with <code>@UIThreadTest</code>. Notice that this will run <em>all</em> of the method statements
265    on the UI thread.  Methods that do not interact with the UI are not allowed; for example, you
266    can't invoke <code>Instrumentation.waitForIdleSync()</code>.
267</p>
268<p>
269    To run a subset of a test method on the UI thread, create an anonymous class of type
270    <code>Runnable</code>, put the statements you want in the <code>run()</code> method, and
271    instantiate a new instance of the class as a parameter to the method
272    <code><em>appActivity</em>.runOnUiThread()</code>, where <code><em>appActivity</em></code> is
273    the instance of the application you are testing.
274</p>
275<p>
276    For example, this code instantiates an activity to test, requests focus (a UI action) for the
277    Spinner displayed by the activity, and then sends a key to it. Notice that the calls to
278    <code>waitForIdleSync</code> and <code>sendKeys</code> aren't allowed to run on the UI thread:
279</p>
280<pre>
281  private MyActivity mActivity; // MyActivity is the class name of the app under test
282  private Spinner mSpinner;
283
284  ...
285
286  protected void setUp() throws Exception {
287      super.setUp();
288      mInstrumentation = getInstrumentation();
289
290      mActivity = getActivity(); // get a references to the app under test
291
292      /*
293       * Get a reference to the main widget of the app under test, a Spinner
294       */
295      mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
296
297  ...
298
299  public void aTest() {
300      /*
301       * request focus for the Spinner, so that the test can send key events to it
302       * This request must be run on the UI thread. To do this, use the runOnUiThread method
303       * and pass it a Runnable that contains a call to requestFocus on the Spinner.
304       */
305      mActivity.runOnUiThread(new Runnable() {
306          public void run() {
307              mSpinner.requestFocus();
308          }
309      });
310
311      mInstrumentation.waitForIdleSync();
312
313      this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
314</pre>
315
316<h3 id="NotouchMode">Turning off touch mode</h3>
317<p>
318    To control the emulator or a device with key events you send from your tests, you must turn off
319    touch mode. If you do not do this, the key events are ignored.
320</p>
321<p>
322    To turn off touch mode, you invoke
323    <code>ActivityInstrumentationTestCase2.setActivityTouchMode(false)</code>
324    <em>before</em> you call <code>getActivity()</code> to start the activity. You must invoke the
325    method in a test method that is <em>not</em> running on the UI thread. For this reason, you
326    can't invoke the touch mode method from a test method that is annotated with
327    <code>@UIThread</code>. Instead, invoke the touch mode method from <code>setUp()</code>.
328</p>
329<h3 id="UnlockDevice">Unlocking the emulator or device</h3>
330<p>
331    You may find that UI tests don't work if the emulator's or device's home screen is disabled with
332    the keyguard pattern. This is because the application under test can't receive key events sent
333    by <code>sendKeys()</code>. The best way to avoid this is to start your emulator or device
334    first and then disable the keyguard for the home screen.
335</p>
336<p>
337    You can also explicitly disable the keyguard. To do this,
338    you need to add a permission in the manifest file (<code>AndroidManifest.xml</code>) and
339    then disable the keyguard in your application under test. Note, though, that you either have to
340    remove this before you publish your application, or you have to disable it with code in
341    the published application.
342</p>
343<p>
344    To add the the permission, add the element
345    <code>&lt;uses-permission android:name="android.permission.DISABLE_KEYGUARD"/&gt;</code>
346    as a child of the <code>&lt;manifest&gt;</code> element. To disable the KeyGuard, add the
347    following code to the <code>onCreate()</code> method of activities you intend to test:
348</p>
349<pre>
350  mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
351  mLock = mKeyGuardManager.newKeyguardLock("<em>activity_classname</em>");
352  mLock.disableKeyguard();
353</pre>
354<p>where <code><em>activity_classname</em></code> is the class name of the activity.</p>
355<h3 id="UITestTroubleshooting">Troubleshooting UI tests</h3>
356<p>
357    This section lists some of the common test failures you may encounter in UI testing, and their
358    causes:
359</p>
360<dl>
361    <dt><code>WrongThreadException</code></dt>
362    <dd>
363      <p><strong>Problem:</strong></p>
364      For a failed test, the Failure Trace contains the following error message:
365      <code>
366        android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created
367        a view hierarchy can touch its views.
368      </code>
369      <p><strong>Probable Cause:</strong></p>
370        This error is common if you tried to send UI events to the UI thread from outside the UI
371        thread. This commonly happens if you send UI events from the test application, but you don't
372        use the <code>@UIThread</code> annotation or the <code>runOnUiThread()</code> method. The
373        test method tried to interact with the UI outside the UI thread.
374      <p><strong>Suggested Resolution:</strong></p>
375        Run the interaction on the UI thread. Use a test class that provides instrumentation. See
376        the previous section <a href="#RunOnUIThread">Testing on the UI Thread</a>
377        for more details.
378    </dd>
379    <dt><code>java.lang.RuntimeException</code></dt>
380    <dd>
381      <p><strong>Problem:</strong></p>
382        For a failed test, the Failure Trace contains the following error message:
383      <code>
384        java.lang.RuntimeException: This method can not be called from the main application thread
385      </code>
386      <p><strong>Probable Cause:</strong></p>
387        This error is common if your test method is annotated with <code>@UiThreadTest</code> but
388        then tries to do something outside the UI thread or tries to invoke
389        <code>runOnUiThread()</code>.
390      <p><strong>Suggested Resolution:</strong></p>
391        Remove the <code>@UiThreadTest</code> annotation, remove the <code>runOnUiThread()</code>
392        call, or re-factor your tests.
393    </dd>
394</dl>
395