Home | History | Annotate | Download | only in testing
      1 page.title=Activity Testing
      2 parent.title=Testing
      3 parent.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