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