1 page.title=Activity Testing Tutorial 2 parent.title=Testing 3 parent.link=index.html 4 @jd:body 5 <div id="qv-wrapper"> 6 <div id="qv"> 7 <h2>In this document</h2> 8 <ol> 9 <li> 10 <a href="#Prerequisites">Prerequisites</a> 11 </li> 12 <li> 13 <a href="#DownloadCode">Installing the Tutorial Sample Code</a> 14 </li> 15 <li> 16 <a href="#SetupEmulator">Setting Up the Emulator</a> 17 </li> 18 <li> 19 <a href="#SetupProjects">Setting Up the Projects</a> 20 </li> 21 <li> 22 <a href="#CreateTestCaseClass">Creating the Test Case Class</a> 23 <ol> 24 <li> 25 <a href="#AddTestCaseClass">Adding the test case class file</a> 26 </li> 27 <li> 28 <a href="#AddConstructor">Adding the test case constructor</a> 29 </li> 30 <li> 31 <a href="#AddSetupMethod">Adding the setup method</a> 32 </li> 33 <li> 34 <a href="#AddPreConditionsTest">Adding an initial conditions test</a> 35 </li> 36 <li> 37 <a href="#AddUITest">Adding a UI test</a> 38 </li> 39 <li> 40 <a href="#StateManagementTests">Adding state management tests</a> 41 </li> 42 </ol> 43 </li> 44 <li> 45 <a href="#RunTests">Running the Tests and Seeing the Results</a> 46 </li> 47 <li> 48 <a href="#TestFailure">Forcing Some Tests to Fail</a> 49 </li> 50 <li> 51 <a href="#NextSteps">Next Steps</a> 52 </li> 53 </ol> 54 <h2 id="#Appendix">Appendix</h2> 55 <ol> 56 <li> 57 <a href="#InstallCompletedTestApp">Installing the Completed Test Application File</a> 58 </li> 59 <li> 60 <a href="#EditorCommandLine">For Users Not Developing In Eclipse</a> 61 </li> 62 </ol> 63 <h2>See Also</h2> 64 <ol> 65 <li> 66 <a href="{@docRoot}tools/testing/testing_android.html">Testing Fundamentals</a> 67 </li> 68 <li> 69 {@link android.test.ActivityInstrumentationTestCase2} 70 </li> 71 <li> 72 {@link junit.framework.Assert} 73 </li> 74 <li> 75 {@link android.test.InstrumentationTestRunner} 76 </li> 77 </ol> 78 </div> 79 </div> 80 <p> 81 Android includes powerful tools for testing applications. The tools extend JUnit with additional features, provide convenience classes for mock Android system objects, and use 82 instrumentation to give you control over your main application while you are testing it. The entire Android testing environment is discussed in the document 83 <a href="{@docRoot}tools/testing/testing_android.html">Testing Fundamentals</a>. 84 </p> 85 <p> 86 This tutorial demonstrates the Android testing tools by presenting a simple Android application and then leading you step-by-step through the creation of a test application for it. 87 The test application demonstrates these key points: 88 </p> 89 <ul> 90 <li> 91 An Android test is itself an Android application that is linked to the application under test by entries in its <code>AndroidManifest.xml</code> file. 92 </li> 93 <li> 94 Instead of Android components, an Android test application contains one or more test cases. Each of these is a separate class definition. 95 </li> 96 <li> 97 Android test case classes extend the JUnit {@link junit.framework.TestCase} class. 98 </li> 99 <li> 100 Android test case classes for activities extend JUnit and also connect you to the application under test with instrumentation. You can send keystroke or touch events directly to the UI. 101 </li> 102 <li> 103 You choose an Android test case class based on the type of component (application, activity, content provider, or service) you are testing. 104 </li> 105 <li> 106 Additional test tools in Eclipse/ADT provide integrated support for creating test applications, running them, and viewing the results. 107 </li> 108 </ul> 109 <p> 110 The test application contains methods that perform the following tests: 111 </p> 112 <ul> 113 <li> 114 Initial conditions test. Tests that the application under test initializes correctly. This is also a unit test of the application's 115 {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method. Testing initial conditions also provides a confidence measure for subsequent tests. 116 </li> 117 <li> 118 UI test. Tests that the main UI operation works correctly. This test demonstrates the instrumentation features available in activity testing. 119 It shows that you can automate UI tests by sending key events from the test application to the main application. 120 </li> 121 <li> 122 State management tests. Test the application's code for saving state. This test demonstrates the instrumentation features of the test runner, which 123 are available for testing any component. 124 </li> 125 </ul> 126 <h2 id="Prerequisites">Prerequisites</h2> 127 <p> 128 The instructions and code in this tutorial depend on the following: 129 </p> 130 <ul> 131 <li> 132 Basic knowledge of Android programming. If you haven't yet written an Android application, 133 do the class 134 <a href="{@docRoot}training/basics/firstapp/index.html">Building Your First App</a>. 135 If you want to learn more about Spinner, the application under test, then you 136 might want to review the "Spinner" sample app. 137 </li> 138 <li> 139 Some familiarity with the Android testing framework and concepts. If you haven't explored 140 Android testing yet, start by reading the 141 <a href="{@docRoot}tools/testing/testing_android.html">Testing Fundamentals</a> 142 guide. 143 </li> 144 <li> 145 Eclipse with ADT. This tutorial describes how to set up and run a test application using 146 Eclipse with ADT. If you haven't yet installed Eclipse and the ADT plugin, 147 follow the steps in <a href="{@docRoot}sdk/installing/index.html">Installing the SDK</a> 148 to install them before continuing. If you are not developing in Eclipse, you will 149 find instructions for setting up and running the test application in the 150 <a href="#EditorCommandLine">appendix</a> of this document. 151 </li> 152 <li> 153 Android 1.5 platform (API Level 3) or higher. You must have the Android 1.5 platform 154 (API Level 3) or higher installed in your SDK, because this tutorial uses APIs that 155 were introduced in that version. 156 <p> 157 If you are not sure which platforms are installed in your SDK, 158 open the Android SDK and AVD Manager and check in the 159 <strong>Installed Packages</strong> panel. 160 If aren't sure how to download a platform into your SDK, 161 read <a href="{@docRoot}sdk/exploring.html">Exploring the SDK</a>. 162 </p> 163 </li> 164 </ul> 165 <h2 id="DownloadCode">Installing the Tutorial Sample Code</h2> 166 <p> 167 During this tutorial, you will be working with sample code that is provided as part 168 of the downloadable Samples component of the SDK. Specifically, you will be working 169 with a pair of related sample applications — an application under test and a test 170 application: 171 </p> 172 <ul> 173 <li> 174 Spinner is the application under test. This tutorial focuses on the 175 common situation of writing tests for an application that already exists, so the main 176 application is provided to you. 177 </li> 178 <li> 179 SpinnerTest is the test application. In the tutorial, you create this application 180 step-by-step. If you want to run quickly through the tutorial, 181 you can install the completed SpinnerTest application first, and then follow the 182 text. You may get more from the tutorial, however, if you create the test application 183 as you go. The instructions for installing the completed test application are in the 184 section 185 <a href="#InstallCompletedTestApp">Installing the Completed Test Application File</a>. 186 </li> 187 </ul> 188 <p> 189 The sample applications are described in more detail in the 190 <a href="{@docRoot}tools/samples/index.html">Samples</a> topic. Follow the instructions to 191 download the version of the samples that's appropriate for the platform you're working with. 192 </p> 193 <h2 id="SetupEmulator">Setting Up the Emulator</h2> 194 <p> 195 In this tutorial, you will use the Android emulator to run applications. The emulator needs 196 an Android Virtual Device (AVD) with an API level equal to or higher than the one you set for the projects in the previous step. 197 To find out how to check this and create the right AVD if necessary, 198 see <a href="{@docRoot}tools/devices/managing-avds.html">Creating an AVD</a>. 199 </p> 200 <p> 201 As a test of the AVD and emulator, run the SpinnerActivity application in Eclipse with ADT. When it starts, 202 click the large downward-pointing arrow to the right of the spinner text. You see the spinner expand and display the title "Select a planet" at the top. 203 Click one of the other planets. The spinner closes, and your selection appears below it on the screen. 204 </p> 205 <h2 id="SetupProjects">Setting Up the Projects</h2> 206 <p> 207 When you are ready to get started with the tutorial, begin by setting up Eclipse projects for 208 both Spinner (the application under test) and SpinnerTest (the test application). 209 </p> 210 <p> 211 You'll be using the Spinner application as-is, without modification, so you'll be loading it 212 into Eclipse as a new Android project from existing source. In the process, you'll be 213 creating a new test project associated with Spinner that will contain the SpinnerTest 214 application. The SpinnerTest application will be completely new and you'll be 215 using the code examples in this tutorial to add test classes and tests to it. 216 </p> 217 <p> 218 To install the Spinner app in a new Android project from existing source, following these steps: 219 </p> 220 <ol> 221 <li> 222 In Eclipse, select <strong>File</strong> > <strong>New</strong> > <strong>Project</strong> > <strong>Android</strong> > <strong>Android Project</strong>, 223 then click Next. The <strong>New Android Project</strong> dialog appears. 224 </li> 225 <li> 226 In the <em>Project name</em> text box, enter "SpinnerActivity". The <em>Properties</em> area is filled in automatically. 227 </li> 228 <li> 229 In the <em>Contents</em> area, set "Create project from existing source". 230 </li> 231 <li> 232 For <em>Location</em>, click <strong>Browse</strong>, navigate to the directory <code><SDK_path>/samples/android-8/Spinner</code>, 233 then click Open. The directory name <code><SDK_path>/samples/android-8/Spinner</code> now appears in the <em>Location</em> text box. 234 </li> 235 <li> 236 In the <em>Build Target</em> area, set a API level of 3 or higher. If you are already developing with a particular target, and it is API level 3 or higher, then use that target. 237 </li> 238 <li> 239 In the <em>Properties</em> area, in the <em>Min SDK Version:</em>, enter "3". 240 </li> 241 <li> 242 You should now see these values: 243 <ul> 244 <li><em>Project Name:</em> "SpinnerActivity"</li> 245 <li><em>Create project from existing source:</em> set</li> 246 <li><em>Location:</em> "<code><SDK_path>/samples/android-8/Spinner</code>"</li> 247 <li><em>Build Target:</em> "API level of 3 or higher" (<em>Target Name</em> "Android 1.5 or higher")</li> 248 <li><em>Package name:</em> (disabled, set to "<code>com.android.example.spinner</code>")</li> 249 <li><em>Create Activity:</em> (disabled, set to ".SpinnerActivity")</li> 250 <li><em>Min SDK Version:</em> "3"</li> 251 </ul> 252 <p> 253 The following screenshot summarizes these values: 254 </p> 255 <a href="{@docRoot}images/testing/eclipse_new_android_project_complete_callouts.png"> 256 <img src="{@docRoot}images/testing/eclipse_new_android_project_complete_callouts.png" alt="New Android Project dialog with filled-in values" style="height:230px"/> 257 </a> 258 259 </li> 260 </ol> 261 <p> 262 To create a new test project for the SpinnerTest application, follow these steps: 263 </p> 264 <ol> 265 <li> 266 Click Next. The <strong>New Android Test Project</strong> dialog appears. 267 </li> 268 <li> 269 Set "Create a Test Project". 270 </li> 271 <li> 272 Leave the other values unchanged. The result should be: 273 <ul> 274 <li><em>Create a Test Project:</em> checked</li> 275 <li><em>Test Project Name:</em> "SpinnerActivityTest"</li> 276 <li><em>Use default location:</em> checked (this should contain the directory name "<code>workspace/SpinnerActivityTest</code>").</li> 277 <li><em>Build Target:</em> Use the same API level you used in the previous step.</li> 278 <li><em>Application name:</em> "SpinnerActivityTest"</li> 279 <li><em>Package name:</em> "<code>com.android.example.spinner.test</code>"</li> 280 <li><em>Min SDK Version:</em> "3"</li> 281 </ul> 282 <p> 283 The following screenshot summarizes these values: 284 </p> 285 <a href="{@docRoot}images/testing/eclipse_new_android_testproject_complete_callouts.png"> 286 <img src="{@docRoot}images/testing/eclipse_new_android_testproject_complete_callouts.png" alt="New Android Test Project dialog with filled-in values" style="height:230px"/> 287 </a> 288 </li> 289 <li> 290 Click Finish. Entries for SpinnerActivity and SpinnerActivityTest should appear in the 291 <strong>Package Explorer</strong>. 292 <p class="note"> 293 <strong>Note:</strong> If you set <em>Build Target</em> to an API level higher than "3", you will see the warning 294 "The API level for the selected SDK target does not match the Min SDK version". You do not need to change the API level or the Min SDK version. 295 The message tells you that you are building the projects with one particular API level, but specifying that a lower API level is required. This may 296 occur if you have chosen not to install the optional earlier API levels. 297 </p> 298 <p> 299 If you see errors listed in the <strong>Problems</strong> pane at the bottom of the Eclipse window, or if a red error marker appears next to 300 the entry for SpinnerActivity in the Package Explorer, highlight the SpinnerActivity entry and then select 301 <strong>Project</strong> > <strong>Clean</strong>. This should fix any errors. 302 </p> 303 </li> 304 </ol> 305 <p> 306 You now have the application under test in the SpinnerActivity project, 307 and an empty test project in SpinnerActivityTest. You may 308 notice that the two projects are in different directories, but Eclipse with 309 ADT handles this automatically. You should have no problem in either building or running them. 310 </p> 311 <p> 312 Notice that Eclipse and ADT have already done some initial setup for your test application. 313 Expand the SpinnerActivityTest project, and notice that it already has an 314 Android manifest file <code>AndroidManifest.xml</code>. 315 Eclipse with ADT created this when you added the test project. 316 Also, the test application is already set up to use instrumentation. You can see this 317 by examining <code>AndroidManifest.xml</code>. 318 Open it, then at the bottom of the center pane click <strong>AndroidManifest.xml</strong> 319 to display the XML contents: 320 </p> 321 <pre> 322 <?xml version="1.0" encoding="utf-8"?> 323 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 324 package="com.android.example.spinner.test" 325 android:versionCode="1" 326 android:versionName="1.0"> 327 <uses-sdk android:minSdkVersion="3" /> 328 <instrumentation 329 android:targetPackage="com.android.example.spinner" 330 android:name="android.test.InstrumentationTestRunner" /> 331 <application android:icon="@drawable/icon" android:label="@string/app_name"> 332 <uses-library android:name="android.test.runner" /> 333 ... 334 </application> 335 </manifest> 336 </pre> 337 <p> 338 Notice the <code><instrumentation></code> element. The attribute 339 <code>android:targetPackage="com.android.example.spinner"</code> tells Android that the 340 application under test is defined in the Android package 341 <code>com.android.example.spinner</code>. Android now knows to use that 342 package's <code>AndroidManifest.xml</code> file to launch the application under test. 343 The <code><instrumentation></code> element also contains the attribute 344 <code>android:name="android.test.InstrumentationTestRunner"</code>, which tells Android 345 instrumentation to run the test application with Android's instrumentation-enabled test runner. 346 </p> 347 <h2 id="CreateTestCaseClass">Creating the Test Case Class</h2> 348 349 <p> 350 You now have a test project SpinnerActivityTest, and the basic structure of a test 351 application also called SpinnerActivityTest. The basic structure includes all the files and 352 directories you need to build and run a test application, except for the class that 353 contains your tests (the test case class). 354 </p> 355 <p> 356 The next step is to define the test case class. In this tutorial, you'll be creating a 357 test case class that includes: 358 </p> 359 <ul> 360 <li> 361 Test setup. This use of the JUnit {@link junit.framework.TestCase#setUp() setUp()} 362 method demonstrates some of the tasks you might perform before running an Android test. 363 </li> 364 <li> 365 Testing initial conditions. This test demonstrates a good testing technique. 366 It also demonstrates that with Android instrumentation you can look at the application 367 under test <em>before</em> the main activity starts. The test checks that the application's 368 important objects have been initialized. 369 If the test fails, you then know that any other tests against the application are 370 unreliable, since the application was running in an incorrect state. 371 <p class="note"> 372 <strong>Note:</strong> The purpose of testing initial conditions is not the same as 373 using <code>setUp()</code>. The JUnit {@link junit.framework.TestCase#setUp()} runs once 374 before <strong>each test method</strong>, and its purpose is to create a clean test 375 environment. The initial conditions test runs once, and its purpose is to verify that the 376 application under test is ready to be tested. 377 </p> 378 </li> 379 <li> 380 Testing the UI. This test shows how to control the main application's UI 381 with instrumentation, a powerful automation feature of Android testing. 382 </li> 383 <li> 384 Testing state management. This test shows some techniques for testing how 385 well the application maintains state in the Android environment. Remember that to 386 provide a satisfactory user experience, your application must never lose its current state, 387 even if it's interrupted by a phone call or destroyed because of memory constraints. 388 The Android activity lifecycle provides ways to maintain state, and the 389 <code>SpinnerActivity</code> application uses them. The test shows the techniques for 390 verifying that they work. 391 </li> 392 </ul> 393 <p> 394 Android tests are contained in a special type of Android application that contains one or more test class definitions. Each of these contains 395 one or more test methods that do the actual tests. In this tutorial, you will first add a test case class, and then add tests to it. 396 </p> 397 <p> 398 You first choose an Android test case class to extend. You choose from the base test case classes according to the Android component you are testing and the types of tests you are doing. 399 In this tutorial, the application under test has a single simple activity, so the test case class will be for an Activity component. Android offers several, but the one that tests in 400 the most realistic environment is {@link android.test.ActivityInstrumentationTestCase2}, so you will use it as the base class. Like all activity test case classes, 401 <code>ActivityInstrumentationTestCase2</code> offers convenience methods for interacting directly with the UI of the application under test. 402 </p> 403 <h3 id="AddTestCaseClass">Adding the test case class file</h3> 404 <p> 405 To add <code>ActivityInstrumentationTestCase2</code> as the base test case class, follow these steps: 406 </p> 407 <ol> 408 <li> 409 In the Package Explorer, expand the test project SpinnerActivityTest if it is not open already. 410 </li> 411 <li> 412 Within SpinnerActivityTest, expand the <code>src/</code> folder and then the package marker for 413 <code>com.android.example.spinner.test</code>. Right-click on the package name and select <strong>New</strong> > <strong>Class</strong>:<br/> 414 <a href="{@docRoot}images/testing/spinner_create_test_class_callouts.png"> 415 <img alt="Menu for creating a new class in the test application" src="{@docRoot}images/testing/spinner_create_test_class_callouts.png" style="height:230px"/> 416 </a> 417 <p> 418 The <strong>New Java Class</strong> wizard appears: 419 </p> 420 <a href="{@docRoot}images/testing/spinnertest_new_class_callouts.png"> 421 <img alt="New Java Class wizard dialog" src="{@docRoot}images/testing/spinnertest_new_class_callouts.png" style="height:230px"/> 422 </a> 423 </li> 424 <li> 425 In the wizard, enter the following: 426 <ul> 427 <li> 428 <em>Name:</em> "SpinnerActivityTest". This becomes the name of your test class. 429 </li> 430 <li> 431 <em>Superclass:</em> "<code>android.test.ActivityInstrumentationTestCase2<SpinnerActivity></code>". The superclass is parameterized, so 432 you have to provide it your main application's class name. 433 </li> 434 </ul> 435 <p> 436 Do not change any of the other settings. Click Finish. 437 </p> 438 </li> 439 <li> 440 You now have a new file <code>SpinnerActivityTest.java</code> in the project. 441 </li> 442 <li> 443 To resolve the reference to SpinnerActivity, add the following import: 444 <pre> 445 import com.android.example.spinner.SpinnerActivity; 446 </pre> 447 </li> 448 </ol> 449 <h3 id="AddConstructor">Adding the test case constructor</h3> 450 <p> 451 To ensure that the test application is instantiated correctly, you must set up a constructor that the test 452 runner will call when it instantiates your test class. This constructor has no parameters, and its sole 453 purpose is to pass information to the superclass's default constructor. To set up this constructor, enter the 454 following code in the class: 455 </p> 456 <pre> 457 public SpinnerActivityTest() { 458 super("com.android.example.spinner", SpinnerActivity.class); 459 } // end of SpinnerActivityTest constructor definition 460 </pre> 461 <p> 462 This calls the superclass constructor with the Android package name (<code>com.android.example.spinner</code>)and main activity's class 463 (<code>SpinnerActivity.class</code>) for the application under test. Android uses this information to find the application and activity to test. 464 </p> 465 <p> 466 You are now ready to add tests, by adding test methods to the class. 467 </p> 468 <h3 id="AddSetupMethod">Adding the setup method</h3> 469 <p> 470 The <code>setUp()</code> method is invoked before every test. You use it to initialize variables and clean up from previous tests. You can also use 471 the JUnit {@link junit.framework.TestCase#tearDown() tearDown()} method, which runs <strong>after</strong> every test method. The tutorial does not use it. 472 </p> 473 <p> 474 The method you are going to add does the following: 475 </p> 476 <ul> 477 <li> 478 <code>super.setUp()</code>. Invokes the superclass constructor for <code>setUp()</code>, which is required by JUnit. 479 </li> 480 <li> 481 Calls {@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode(false)}. 482 This turns off <strong>touch mode</strong> in the device or emulator. If any of your test methods send key events to the application, 483 you must turn off touch mode <em>before</em> you start any activities; otherwise, the call is ignored. 484 </li> 485 <li> 486 Stores references to system objects. Retrieves and stores a reference to the activity under test, the <code>Spinner</code> 487 widget used by the activity, the <code>SpinnerAdapter</code> that backs the widget, and the string value of the selection that is 488 set when the application is first installed. These objects are used in the state management test. The methods invoked are: 489 <ul> 490 <li> 491 {@link android.test.ActivityInstrumentationTestCase2#getActivity()}. Gets a reference to the activity under test (<code>SpinnerActivity</code>). 492 This call also starts the activity if it is not already running. 493 </li> 494 <li> 495 {@link android.app.Activity#findViewById(int)}. Gets a reference to the <code>Spinner</code> widget of the application under test. 496 </li> 497 <li> 498 {@link android.widget.AbsSpinner#getAdapter()}. Gets a reference to the adapter (an array of strings) backing the spinner. 499 </li> 500 </ul> 501 </li> 502 </ul> 503 <p> 504 Add this code to the definition of <code>SpinnerActivityTest</code>, after the constructor definition: 505 </p> 506 <pre> 507 @Override 508 protected void setUp() throws Exception { 509 super.setUp(); 510 511 setActivityInitialTouchMode(false); 512 513 mActivity = getActivity(); 514 515 mSpinner = 516 (Spinner) mActivity.findViewById( 517 com.android.example.spinner.R.id.Spinner01 518 ); 519 520 mPlanetData = mSpinner.getAdapter(); 521 522 } // end of setUp() method definition 523 </pre> 524 <p> 525 Add these members to the test case class: 526 </p> 527 <pre> 528 private SpinnerActivity mActivity; 529 private Spinner mSpinner; 530 private SpinnerAdapter mPlanetData; 531 </pre> 532 <p> 533 Add these imports: 534 </p> 535 <pre> 536 import android.widget.Spinner; 537 import android.widget.SpinnerAdapter; 538 </pre> 539 <p> 540 You now have the the complete <code>setUp()</code> method. 541 </p> 542 <h3 id="AddPreConditionsTest">Adding an initial conditions test</h3> 543 <p> 544 The initial conditions test verifies that the application under test is initialized correctly. It is an illustration of the types of tests you can run, so it is not comprehensive. 545 It verifies the following: 546 </p> 547 <ul> 548 <li> 549 The item select listener is initialized. This listener is called when a selection is made from the spinner. 550 </li> 551 <li> 552 The adapter that provides values to the spinner is initialized. 553 </li> 554 <li> 555 The adapter contains the right number of entries. 556 </li> 557 </ul> 558 <p> 559 The actual initialization of the application under test is done in <code>setUp()</code>, which the test runner calls automatically before every test. The verifications are 560 done with JUnit {@link junit.framework.Assert} calls. As a useful convention, the method name is <code>testPreConditions()</code>: 561 </p> 562 <pre> 563 public void testPreConditions() { 564 assertTrue(mSpinner.getOnItemSelectedListener() != null); 565 assertTrue(mPlanetData != null); 566 assertEquals(mPlanetData.getCount(),ADAPTER_COUNT); 567 } // end of testPreConditions() method definition 568 </pre> 569 <p> 570 Add this member: 571 </p> 572 <pre> 573 public static final int ADAPTER_COUNT = 9; 574 </pre> 575 <h3 id="AddUITest">Adding a UI test</h3> 576 <p> 577 Now create a UI test that selects an item from the <code>Spinner</code> widget. The test sends key events to the UI with key events. 578 The test confirms that the selection matches the result you expect. 579 </p> 580 <p> 581 This test demonstrates the power of using instrumentation in Android testing. Only an instrumentation-based test class allows you to send key events (or touch events) 582 to the application under test. With instrumentation, you can test your UI without having to take screenshots, record the screen, or do human-controlled testing. 583 </p> 584 <p> 585 To work with the spinner, the test has to request focus for it and then set it to a known position. The test uses {@link android.view.View#requestFocus() requestFocus()} and 586 {@link android.widget.AbsSpinner#setSelection(int) setSelection()} to do this. Both of these methods interact with a View in the application under test, so you have to call them 587 in a special way. 588 </p> 589 <p> 590 Code in a test application that interacts with a View of the application under test must run in the main application's thread, also 591 known as the <em>UI thread</em>. To do this, you use the {@link android.app.Activity#runOnUiThread(java.lang.Runnable) Activity.runOnUiThread()} 592 method. You pass the code to <code>runOnUiThread()</code>in an anonymous {@link java.lang.Runnable Runnable} object. To set 593 the statements in the <code>Runnable</code> object, you override the object's {@link java.lang.Runnable#run()} method. 594 </p> 595 <p> 596 To send key events to the UI of the application under test, you use the <a href="{@docRoot}reference/android/test/InstrumentationTestCase.html#sendKeys(int...)">sendKeys</a>() method. 597 This method does not have to run on the UI thread, since Android uses instrumentation to pass the key events to the application under test. 598 </p> 599 <p> 600 The last part of the test compares the selection made by sending the key events to a pre-determined value. This tests that the spinner is working as intended. 601 </p> 602 <p> 603 The following sections show you how to add the code for this test. 604 </p> 605 <ol> 606 <li> 607 Get focus and set selection. Create a new method <code>public void testSpinnerUI()</code>. Add 608 code to to request focus for the spinner and set its position to default or initial position, "Earth". This code is run on the UI thread of 609 the application under test: 610 <pre> 611 public void testSpinnerUI() { 612 613 mActivity.runOnUiThread( 614 new Runnable() { 615 public void run() { 616 mSpinner.requestFocus(); 617 mSpinner.setSelection(INITIAL_POSITION); 618 } // end of run() method definition 619 } // end of anonymous Runnable object instantiation 620 ); // end of invocation of runOnUiThread 621 </pre> 622 <p> 623 Add the following member to the test case class. 624 </p> 625 <pre> 626 public static final int INITIAL_POSITION = 0; 627 </pre> 628 </li> 629 <li> 630 Make a selection. Send key events to the spinner to select one of the items. To do this, open the spinner by 631 "clicking" the center keypad button (sending a DPAD_CENTER key event) and then clicking (sending) the down arrow keypad button five times. Finally, 632 click the center keypad button again to highlight the desired item. Add the following code: 633 <pre> 634 this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 635 for (int i = 1; i <= TEST_POSITION; i++) { 636 this.sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 637 } // end of for loop 638 639 this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 640 </pre> 641 <p> 642 Add the following member to the test case class: 643 </p> 644 <pre> 645 public static final int TEST_POSITION = 5; 646 </pre> 647 <p> 648 This sets the final position of the spinner to "Saturn" (the spinner's backing adapter is 0-based). 649 </p> 650 </li> 651 <li> 652 Check the result. Query the current state of the spinner, and compare its current selection to the expected value. 653 Call the method {@link android.widget.AdapterView#getSelectedItemPosition() getSelectedItemPosition()} to find out the current selection position, and then 654 {@link android.widget.AdapterView#getItemAtPosition(int) getItemAtPosition()} to get the object corresponding to that position (casting it to a String). Assert that 655 this string value matches the expected value of "Saturn": 656 <pre> 657 mPos = mSpinner.getSelectedItemPosition(); 658 mSelection = (String)mSpinner.getItemAtPosition(mPos); 659 TextView resultView = 660 (TextView) mActivity.findViewById( 661 com.android.example.spinner.R.id.SpinnerResult 662 ); 663 664 String resultText = (String) resultView.getText(); 665 666 assertEquals(resultText,mSelection); 667 668 } // end of testSpinnerUI() method definition 669 </pre> 670 <p> 671 Add the following members to the test case class: 672 </p> 673 <pre> 674 private String mSelection; 675 private int mPos; 676 </pre> 677 <p> 678 Add the following imports to the test case class: 679 </p> 680 <pre> 681 import android.view.KeyEvent; 682 import android.widget.TextView; 683 </pre> 684 </li> 685 </ol> 686 <p> 687 Pause here to run the tests you have. The procedure for running a test application is different 688 from running a regular Android application. You run a test application as an Android JUnit 689 application. To see how to do this, see <a href="#RunTests">Running the Tests and Seeing the Results</a>. 690 </p> 691 <p> 692 Eventually, you will see the <code>SpinnerActivity</code> application start, and the test 693 application controlling it by sending it key events. You will also see a new 694 <strong>JUnit</strong> view in the Explorer pane, showing the results of the 695 test. The JUnit view is documented in a following section, 696 <a href="#RunTests">Running the Test and Seeing the Results</a>. 697 </p> 698 <h3 id="StateManagementTests">Adding state management tests</h3> 699 <p> 700 You now write two tests that verify that SpinnerActivity maintains its state when it is paused or terminated. 701 The state, in this case, is the current selection in the spinner. When users make a selection, 702 pause or terminate the application, and then resume or restart it, they should see 703 the same selection. 704 </p> 705 <p> 706 Maintaining state is an important feature of an application. Users may switch from the current 707 application temporarily to answer the phone, and then switch back. Android may decide to 708 terminate and restart an activity to change the screen orientation, or terminate an unused 709 activity to regain storage. In each case, users are best served by having the UI return to its 710 previous state (except where the logic of the application dictates otherwise). 711 </p> 712 <p> 713 SpinnerActivity manages its state in these ways: 714 </p> 715 <ul> 716 <li> 717 Activity is hidden. When the spinner screen (the activity) is running but hidden by some other screen, it 718 stores the spinner's position and value in a form that persists while the application is running. 719 </li> 720 <li> 721 Application is terminated. When the activity is terminated, it stores the spinner's position and value in 722 a permanent form. The activity can read the position and value when it restarts, and restore the spinner to its previous state. 723 </li> 724 <li> 725 Activity re-appears. When the user returns to the spinner screen, the previous selection is restored. 726 </li> 727 <li> 728 Application is restarted. When the user starts the application again, the previous selection is restored. 729 </li> 730 </ul> 731 <p class="note"> 732 <strong>Note:</strong> An application can manage its state in other ways as well, but these are 733 not covered in this tutorial. 734 </p> 735 <p> 736 When an activity is hidden, it is <strong>paused</strong>. When it re-appears, it 737 <strong>resumes</strong>. Recognizing that these are key points in an activity's life cycle, 738 the Activity class provides two callback methods {@link android.app.Activity#onPause()} and 739 {@link android.app.Activity#onResume()} for handling pauses and resumes. 740 SpinnerActivity uses them for code that saves and restores state. 741 </p> 742 <p> 743 <strong>Note:</strong> If you would like to learn more about the difference between losing 744 focus/pausing and killing an application, 745 read about the <a href="{@docRoot}guide/components/activities.html#Lifecycle">activity 746 lifecycle</a>. 747 </p> 748 <p> 749 The first test verifies that the spinner selection is maintained after the entire application is shut down and then restarted. The test uses instrumentation to 750 set the spinner's variables outside of the UI. It then terminates the activity by calling {@link android.app.Activity#finish() Activity.finish()}, and restarts it 751 using the instrumentation method {@link android.test.ActivityInstrumentationTestCase2#getActivity()}. The test then asserts that the current spinner state matches 752 the test values. 753 </p> 754 <p> 755 The second test verifies that the spinner selection is maintained after the activity is paused and then resumed. The test uses instrumentation to 756 set the spinner's variables outside of the UI and then force calls to the <code>onPause()</code> and <code>onResume()</code> methods. The test then 757 asserts that the current spinner state matches the test values. 758 </p> 759 <p> 760 Notice that these tests make limited assumptions about the mechanism by which the activity manages state. The tests use the activity's getters and 761 setters to control the spinner. The first test also knows that hiding an activity calls <code>onPause()</code>, and bringing it back to the foreground 762 calls <code>onResume()</code>. Other than this, the tests treat the activity as a "black box". 763 </p> 764 <p> 765 To add the code for testing state management across shutdown and restart, follow these steps: 766 </p> 767 <ol> 768 <li> 769 Add the test method <code>testStateDestroy()</code>, then 770 set the spinner selection to a test value: 771 <pre> 772 public void testStateDestroy() { 773 mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION); 774 mActivity.setSpinnerSelection(TEST_STATE_DESTROY_SELECTION); 775 </pre> 776 </li> 777 <li> 778 Terminate the activity and restart it: 779 <pre> 780 mActivity.finish(); 781 mActivity = this.getActivity(); 782 </pre> 783 </li> 784 <li> 785 Get the current spinner settings from the activity: 786 <pre> 787 int currentPosition = mActivity.getSpinnerPosition(); 788 String currentSelection = mActivity.getSpinnerSelection(); 789 </pre> 790 </li> 791 <li> 792 Test the current settings against the test values: 793 <pre> 794 assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition); 795 assertEquals(TEST_STATE_DESTROY_SELECTION, currentSelection); 796 } // end of testStateDestroy() method definition 797 </pre> 798 <p> 799 Add the following members to the test case class: 800 <pre> 801 public static final int TEST_STATE_DESTROY_POSITION = 2; 802 public static final String TEST_STATE_DESTROY_SELECTION = "Earth"; 803 </pre> 804 </li> 805 </ol> 806 <p> 807 To add the code for testing state management across a pause and resume, follow these steps: 808 </p> 809 <ol> 810 <li> 811 Add the test method <code>testStatePause()</code>: 812 <pre> 813 @UiThreadTest 814 public void testStatePause() { 815 </pre> 816 <p> 817 The <code>@UiThreadTest</code> annotation tells Android to build this method so that it runs 818 on the UI thread. This allows the method to change the state of the spinner widget in the 819 application under test. This use of <code>@UiThreadTest</code> shows that, if necessary, you 820 can run an entire method on the UI thread. 821 </p> 822 </li> 823 <li> 824 Set up instrumentation. Get the instrumentation object 825 that is controlling the application under test. This is used later to 826 invoke the <code>onPause()</code> and <code>onResume()</code> methods: 827 <pre> 828 Instrumentation mInstr = this.getInstrumentation(); 829 </pre> 830 </li> 831 <li> 832 Set the spinner selection to a test value: 833 <pre> 834 mActivity.setSpinnerPosition(TEST_STATE_PAUSE_POSITION); 835 mActivity.setSpinnerSelection(TEST_STATE_PAUSE_SELECTION); 836 </pre> 837 </li> 838 <li> 839 Use instrumentation to call the Activity's <code>onPause()</code>: 840 <pre> 841 mInstr.callActivityOnPause(mActivity); 842 </pre> 843 <p> 844 Under test, the activity is waiting for input. The invocation of 845 {@link android.app.Instrumentation#callActivityOnPause(android.app.Activity)} 846 performs a call directly to the activity's <code>onPause()</code> instead 847 of manipulating the activity's UI to force it into a paused state. 848 </p> 849 </li> 850 <li> 851 Force the spinner to a different selection: 852 <pre> 853 mActivity.setSpinnerPosition(0); 854 mActivity.setSpinnerSelection(""); 855 </pre> 856 <p> 857 This ensures that resuming the activity actually restores the 858 spinner's state rather than simply leaving it as it was. 859 </p> 860 </li> 861 <li> 862 Use instrumentation to call the Activity's <code>onResume()</code>: 863 <pre> 864 mInstr.callActivityOnResume(mActivity); 865 </pre> 866 <p> 867 Invoking {@link android.app.Instrumentation#callActivityOnResume(android.app.Activity)} 868 affects the activity in a way similar to <code>callActivityOnPause</code>. The 869 activity's <code>onResume()</code> method is invoked instead of manipulating the 870 activity's UI to force it to resume. 871 </p> 872 </li> 873 <li> 874 Get the current state of the spinner: 875 <pre> 876 int currentPosition = mActivity.getSpinnerPosition(); 877 String currentSelection = mActivity.getSpinnerSelection(); 878 </pre> 879 </li> 880 <li> 881 Test the current spinner state against the test values: 882 <pre> 883 assertEquals(TEST_STATE_PAUSE_POSITION,currentPosition); 884 assertEquals(TEST_STATE_PAUSE_SELECTION,currentSelection); 885 } // end of testStatePause() method definition 886 </pre> 887 <p> 888 Add the following members to the test case class: 889 </p> 890 <pre> 891 public static final int TEST_STATE_PAUSE_POSITION = 4; 892 public static final String TEST_STATE_PAUSE_SELECTION = "Jupiter"; 893 </pre> 894 </li> 895 <li> 896 Add the following imports: 897 <pre> 898 import android.app.Instrumentation; 899 import android.test.UiThreadTest; 900 </pre> 901 </li> 902 </ol> 903 <h2 id="RunTests">Running the Tests and Seeing the Results</h2> 904 <p> 905 The most simple way to run the <code>SpinnerActivityTest</code> test case is to run it directly from the Package Explorer. 906 </p> 907 <p> 908 To run the <code>SpinnerActivityTest</code> test, follow these steps: 909 </p> 910 <ol> 911 <li> 912 In the Package Explorer, right-click the project SpinnerActivityTest at the top level, and then 913 select <strong>Run As</strong> > <strong>Android JUnit Test</strong>:<br/> 914 <a href="{@docRoot}images/testing/spinnertest_runas_menu_callouts.png"> 915 <img alt="Menu to run a test as an Android JUnit test" src="{@docRoot}images/testing/spinnertest_runas_menu_callouts.png" style="height:230px"> 916 </a> 917 </li> 918 <li> 919 You will see the emulator start. When the unlock option is displayed (its appearance depends on the API level you specified for the AVD), 920 unlock the home screen. 921 </li> 922 <li> 923 The test application starts. You see a new tab for the <strong>JUnit</strong> view, next to the Package Explorer tab:<br/> 924 <a href="{@docRoot}images/testing/spinnertest_junit_panel.png"> 925 <img alt="The JUnit window" src="{@docRoot}images/testing/spinnertest_junit_panel.png" style="height:230px"> 926 </a> 927 </li> 928 </ol> 929 <p> 930 This view contains two sub-panes. The top pane summarizes the tests that were run, and the bottom pane shows failure traces for 931 highlighted tests. 932 </p> 933 <p> 934 At the conclusion of a successful test run, this is the view's appearance:<br/> 935 <a href="{@docRoot}images/testing/spinnertest_junit_success.png"> 936 <img src="{@docRoot}images/testing/spinnertest_junit_success.png" alt="JUnit test run success" style="height:230px"/> 937 </a> 938 </p> 939 <p> 940 The upper pane summarizes the test: 941 </p> 942 <ul> 943 <li> 944 Total time elapsed for the test application(labeled <em>Finished after <x> seconds</em>). 945 </li> 946 <li> 947 Number of runs (<em>Runs:</em>) - the number of tests in the entire test class. 948 </li> 949 <li> 950 Number of errors (<em>Errors:</em>) - the number of program errors and exceptions encountered during 951 the test run. 952 </li> 953 <li> 954 Number of failures (<em>Failures:</em>) - the number of test failures encountered during the test 955 run. This is the number of assertion failures. A test can fail even if the program does not encounter an error. 956 </li> 957 <li> 958 A progress bar. The progress bar extends from left to right as the tests run. 959 <p> 960 If all the tests succeed, the bar remains green. If a test fails, the bar turns from green to red. 961 </p> 962 </li> 963 <li> 964 A test method summary. Below the bar, you see a line for each class in the test application. To look at the results for the individual 965 methods in a test, click the arrow at the left to expand the line. You see the name of each test method. To the 966 right of the name, you see the time taken by the test. You can look at the test's code 967 by double-clicking its name. 968 </li> 969 </ul> 970 <p> 971 The lower pane contains the failure trace. If all the tests are successful, this pane is empty. If some tests fail, 972 then if you highlight a failed test in the upper pane, the lower view contains a stack trace for the test. This is 973 demonstrated in the next section. 974 </p> 975 <p class="note"> 976 <strong>Note:</strong> If you run the test application and nothing seems to happen, look for 977 the JUnit view. If you do not see it, you may have run the test application 978 as a regular Android application. 979 Remember that you need to run it as an Android <strong>JUnit</strong> 980 application. 981 </p> 982 <h2 id="TestFailure">Forcing Some Tests to Fail</h2> 983 <p> 984 A test is as useful when it fails as when it succeeds. This section shows what happens in Eclipse with ADT when a test fails. You 985 can quickly see that a test class has failed, find the method or methods that failed, and then use a failure trace to find 986 the exact problem. 987 </p> 988 <p> 989 The example application SpinnerActivity that you downloaded passes all the tests in the test application SpinnerActivityTest. 990 To force the test to fail, you must modify the example application. You change a line of setup code in the application under test. This 991 causes the <code>testPreConditions()</code> and <code>testTextView()</code> test methods to fail. 992 </p> 993 <p> 994 To force the tests to fail, follow these steps: 995 </p> 996 <ol> 997 <li> 998 In Eclipse with ADT, go to the SpinnerActivity project and open the file <code>SpinnerActivity.java</code>. 999 </li> 1000 <li> 1001 At the top of <code>SpinnerActivity.java</code>, at the end of the <code>onCreate()</code> method, find the following line: 1002 <pre> 1003 // mySpinner.setOnItemSelectedListener(null); 1004 </pre> 1005 <p>Remove the forward slash characters at the beginning of the line to 1006 uncomment the line. This sets the listener callback to null: 1007 </p> 1008 <pre> 1009 mySpinner.setOnItemSelectedListener(null); 1010 </pre> 1011 </li> 1012 <li> 1013 The <code>testPreConditions()</code> method in <code>SpinnerActivityTest</code> contains the following test: 1014 <code>assertTrue(mSpinner.getOnItemSelectedListener() != null);</code>. This test asserts that the listener callback is <em>not</em> null. 1015 Since you have modified the application under test, this assertion now fails. 1016 </li> 1017 <li> 1018 Run the test, as described in the previous section <a href="#RunTests">Running the Tests and Seeing the Results</a>. 1019 </li> 1020 </ol> 1021 <p> 1022 The JUnit view is either created or updated with the results of the test. Now, however, the progress bar is red, 1023 the number of failures is 2, and small "x" icons appear in the list icons next to the testPreConditions and 1024 TestSpinnerUI tests. This indicates that the tests have failed. The display is similar to this:<br/> 1025 <a href="{@docRoot}images/testing/spinnertest_junit_panel_fail_callouts.png"> 1026 <img src="{@docRoot}images/testing/spinnertest_junit_panel_fail_callouts.png" alt="The JUnit Failure window" style="height:230px"/> 1027 </a> 1028 </p> 1029 <p> 1030 You now want to look at the failures to see exactly where they occurred. 1031 </p> 1032 <p> 1033 To examine the failures, follow these steps: 1034 </p> 1035 <ol> 1036 <li> 1037 Click the testPreconditions entry. In the lower pane entitled <strong>Failure Trace</strong>, 1038 you see a stack trace of the calls that led to the failure. This trace is similar to the following screenshot:<br/> 1039 <a href="{@docRoot}images/testing/spinnertest_junit_panel_failtrace_callouts.png"> 1040 <img src="{@docRoot}images/testing/spinnertest_junit_panel_failtrace_callouts.png" alt="The JUnit failure trace" style="height:230px"/> 1041 </a> 1042 </li> 1043 <li> 1044 The first line of the trace tells you the error. In this case, a JUnit assertion failed. To look at the 1045 assertion in the test code, double-click the next line (the first line of the trace). In the center pane 1046 a new tabbed window opens, containing the code for the test application <code>SpinnerActivityTest</code>. The failed assertion 1047 is highlighted in the middle of the window. 1048 </li> 1049 </ol> 1050 <p> 1051 The assertion failed because you modified the main application to set the <code>getOnItemSelectedListener</code> callback to <code>null</code>. 1052 </p> 1053 <p> 1054 You can look at the failure in <code>testTextView</code> if you want. Remember, though, that <code>testPreConditions</code> is meant to verify the 1055 initial setup of the application under test. If testPreConditions() fails, then succeeding tests can't be trusted. The best strategy to follow is to 1056 fix the problem and re-run all the tests. 1057 </p> 1058 <p> 1059 Remember to go back to <code>SpinnerActivity.java</code> and re-comment the line you uncommented in an earlier step. 1060 </p> 1061 <p> 1062 You have now completed the tutorial. 1063 </p> 1064 <h2 id="NextSteps">Next Steps</h2> 1065 <p> 1066 This example test application has shown you how to create a test project and link it to 1067 the application you want to test, how to choose and add a test case class, how to write 1068 UI and state management tests, and how to run the tests against the application under 1069 test. Now that you are familiar with the basics of testing Android applications, here 1070 are some suggested next steps: 1071 </p> 1072 <p> 1073 <strong>Learn more about testing on Android</strong> 1074 </p> 1075 <ul> 1076 <li> 1077 If you haven't done so already, read the 1078 <a href="{@docRoot}tools/testing/testing_android.html">Testing Fundamentals</a> 1079 document in the <em>Dev Guide</em>. It provides an overview of how testing on Android 1080 works. If you are just getting started with Android testing, reading that document will 1081 help you understand the tools available to you, so that you can develop effective 1082 tests. 1083 </li> 1084 </ul> 1085 <p> 1086 <strong>Review the main Android test case classes</strong> 1087 </p> 1088 <ul> 1089 <li> 1090 {@link android.test.ActivityInstrumentationTestCase2} 1091 </li> 1092 <li> 1093 {@link android.test.ActivityUnitTestCase} 1094 </li> 1095 <li> 1096 {@link android.test.ProviderTestCase2} 1097 </li> 1098 <li> 1099 {@link android.test.ServiceTestCase} 1100 </li> 1101 </ul> 1102 <p> 1103 <strong>Learn more about the assert and utility classes</strong> 1104 </p> 1105 <ul> 1106 <li> 1107 {@link junit.framework.Assert}, the JUnit Assert class. 1108 </li> 1109 <li> 1110 {@link android.test.MoreAsserts}, additional Android assert methods. 1111 </li> 1112 <li> 1113 {@link android.test.ViewAsserts}, useful assertion methods for testing Views. 1114 </li> 1115 <li> 1116 {@link android.test.TouchUtils}, utility methods for simulating touch events in an Activity. 1117 </li> 1118 </ul> 1119 <p> 1120 <strong>Learn about instrumentation and the instrumented test runner</strong> 1121 </p> 1122 <ul> 1123 <li> 1124 {@link android.app.Instrumentation}, the base instrumentation class. 1125 </li> 1126 <li> 1127 {@link android.test.InstrumentationTestCase}, the base instrumentation test case. 1128 </li> 1129 <li> 1130 {@link android.test.InstrumentationTestRunner}, the standard Android test runner. 1131 </li> 1132 </ul> 1133 <h2 id="Appendix">Appendix</h2> 1134 <h3 id="InstallCompletedTestApp">Installing the Completed Test Application File</h3> 1135 <p> 1136 The recommended approach to this tutorial is to follow the instructions step-by-step and 1137 write the test code as you go. However, if you want to do this tutorial quickly, 1138 you can install the entire file for the test application into the test project. 1139 </p> 1140 <p> 1141 To do this, you first create a test project with the necessary structure and files by using 1142 the automated tools in Eclipse. Then you exit Eclipse and copy the test application's file 1143 from the SpinnerTest sample project into your test project. The SpinnerTest sample project is 1144 part of the Samples component of the SDK. 1145 </p> 1146 <p> 1147 The result is a complete test application, ready to run against the Spinner sample application. 1148 </p> 1149 <p> 1150 To install the test application file, follow these steps: 1151 </p> 1152 <ol> 1153 <li> 1154 Set up the projects for the application under test and the test application, as described 1155 in the section section <a href="#SetupProjects">Setting Up the Projects</a>. 1156 </li> 1157 <li> 1158 Set up the emulator, as described in the section <a href="#SetupEmulator">Setting Up the Emulator</a>. 1159 </li> 1160 <li> 1161 Add the test case class, as described in the section <a href="#AddTestCaseClass">Adding the test case class file</a>. 1162 </li> 1163 <li> 1164 Close Eclipse with ADT. 1165 </li> 1166 <li> 1167 Copy the file <code><SDK_path>/samples/android-8/SpinnerTest/src/com/android/example/spinner/test/SpinnerActivityTest.java</code> 1168 to the directory <code>workspace/SpinnerActivityTest/src/com/android/example/spinner/test/</code>. 1169 </li> 1170 <li> 1171 Restart Eclipse with ADT. 1172 </li> 1173 <li> 1174 In Eclipse with ADT, re-build the project <code>SpinnerActivityTest</code> by selecting it in the Package Explorer, right-clicking, 1175 and selecting <em>Project</em> > <em>Clean</em>. 1176 </li> 1177 <li> 1178 The complete, working test application should now be in the <code>SpinnerActivityTest</code> project. 1179 </li> 1180 </ol> 1181 <p> 1182 You can now continue with the tutorial, starting at the section <a href="#AddConstructor">Adding the test case constructor</a> and 1183 following along in the text. 1184 </p> 1185 <h3 id="EditorCommandLine">For Users Not Developing In Eclipse</h3> 1186 <p> 1187 If you are not developing in Eclipse, you can still do this tutorial. Android provides tools for 1188 creating test applications using a code editor and command-line tools. You use the following tools: 1189 </p> 1190 <ul> 1191 <li> 1192 <a href="{@docRoot}tools/help/adb.html">adb</a> - Installs and uninstalls applications and test applications to a device or the emulator. You 1193 also use this tool to run the test application from the command line. 1194 </li> 1195 <li> 1196 <a href="{@docRoot}tools/help/android.html">android</a> - Manages projects and test projects. This tool also manages AVDs and Android platforms. 1197 </li> 1198 </ul> 1199 <p> 1200 You use the <code>emulator</code> tool to run the emulator from the command line. 1201 </p> 1202 <p> 1203 Here are the general steps for doing this tutorial using an editor and the command line: 1204 </p> 1205 <ol> 1206 <li> 1207 As described in the section <a href="#DownloadCode">Installing the Tutorial Sample Code</a>, get the sample code. You will then 1208 have a directory <code><SDK_path>/samples/android-8</code>, containing (among others) the directories <code>Spinner</code> 1209 and <code>SpinnerTest</code>: 1210 <ul> 1211 <li> 1212 <code>Spinner</code> contains the main application, also known as the <strong>application under test</strong>. This tutorial focuses on the 1213 common situation of writing tests for an application that already exists, so the main application is provided to you. 1214 </li> 1215 <li> 1216 <code>SpinnerTest</code> contains all the code for the test application. If you want to run quickly through the tutorial, you can 1217 install the test code and then follow the text. You may get more from the tutorial, however, if you write the code as you go. The instructions 1218 for installing the test code are in the section <a href="#InstallCompletedTestApp">Appendix: Installing the Completed Test Application File</a>. 1219 </li> 1220 </ul> 1221 </li> 1222 <li> 1223 Navigate to the directory <code><SDK_path>/samples/android-8</code>. 1224 </li> 1225 <li> 1226 Create a new Android application project using <code>android create project</code>: 1227 <pre> 1228 $ android create project -t <APItarget> -k com.android.example.spinner -a SpinnerActivity -n SpinnerActivity -p Spinner 1229 </pre> 1230 <p> 1231 The value of <code><APItarget></code> should be "3" (API level 3) or higher. If you are already developing with a particular API level, and it is 1232 higher than 3, then use that API level. 1233 </p> 1234 <p> 1235 This a new Android project <code>SpinnerActivity</code> in the existing <code>Spinner</code> directory. The existing source and 1236 resource files are not touched, but the <code>android</code> tool adds the necessary build files. 1237 </p> 1238 </li> 1239 <li> 1240 Create a new Android test project using <code>android create test-project</code>: 1241 <pre> 1242 $ android create test-project -m ../Spinner -n SpinnerActivityTest -p SpinnerActivityTest 1243 </pre> 1244 <p> 1245 This will create a new Android test project in the <em>new</em> directory <code>SpinnerActivityTest</code>. You do this 1246 so that the solution to the tutorial that is in <code>SpinnerTest</code> is left untouched. If you want to use the solution 1247 code instead of entering it as you read through the tutorial, refer to the section 1248 <a href="#InstallCompletedTestApp">Appendix: Installing the Completed Test Application File</a>. 1249 </p> 1250 <p class="Note"> 1251 <strong>Note:</strong> Running <code>android create test-project</code> will automatically create 1252 the file <code>AndroidManifest.xml</code> with the correct <code><instrumentation></code> element. 1253 </p> 1254 </li> 1255 <li> 1256 Build the sample application. If you are building with Ant, then it is easiest to use the command <code>ant debug</code> to build a debug version, since the SDK comes 1257 with a debug signing key. The result will be the file <code>Spinner/bin/SpinnerActivity-debug.apk</code>. 1258 You can install this to your device or emulator. Attach your device or start the emulator if you haven't already, and run the command: 1259 <pre> 1260 $ adb install Spinner/bin/SpinnerActivity-debug.apk 1261 </pre> 1262 </li> 1263 <li> 1264 To create the test application, create a file <code>SpinnerActivityTest.java</code> in the directory 1265 <code>SpinnerActivityTest/src/com/android/example/spinner/test/</code>. 1266 </li> 1267 <li> 1268 Follow the tutorial, starting with the section <a href="#CreateTestCaseClass">Creating the Test Case Class</a>. When you are prompted to 1269 run the sample application, go the the Launcher screen in your device or emulator and select SpinnerActivity. 1270 When you are prompted to run the test application, return here to continue with the following instructions. 1271 </li> 1272 <li> 1273 Build the test application. If you are building with Ant, then it is easiest to use the command <code>ant debug</code> to build a 1274 debug version, since the SDK comes with a debug signing key. The result will be the Android file 1275 <code>SpinnerActivityTest/bin/SpinnerActivityTest-debug.apk</code>. You can install this to your device or emulator. 1276 Attach your device or start the emulator if you haven't already, and run the command: 1277 <pre> 1278 $ adb install SpinnerActivityTest/bin/SpinnerActivityTest-debug.apk 1279 </pre> 1280 </li> 1281 <li> 1282 In your device or emulator, check that both the main application <code>SpinnerActivity</code> and the test application 1283 <code>SpinnerActivityTest</code> are installed. 1284 </li> 1285 <li> 1286 To run the test application, enter the following at the command line: 1287 <pre> 1288 $ adb shell am instrument -w com.android.example.spinner.test/android.test.InstrumentationTestRunner 1289 </pre> 1290 </li> 1291 </ol> 1292 <p> 1293 The result of a successful test looks like this: 1294 </p> 1295 <pre> 1296 com.android.example.spinner.test.SpinnerActivityTest:.... 1297 Test results for InstrumentationTestRunner=.... 1298 Time: 10.098 1299 OK (4 tests) 1300 </pre> 1301 <p> 1302 If you force the test to fail, as described in the previous section <a href="#TestFailure">Forcing Some Tests to Fail</a>, then 1303 the output looks like this: 1304 </p> 1305 <pre> 1306 com.android.example.spinner.test.SpinnerActivityTest: 1307 Failure in testPreConditions: 1308 junit.framework.AssertionFailedError 1309 at com.android.example.spinner.test.SpinnerActivityTest.testPreConditions(SpinnerActivityTest.java:104) 1310 at java.lang.reflect.Method.invokeNative(Native Method) 1311 at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205) 1312 at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195) 1313 at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:175) 1314 at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) 1315 at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) 1316 at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430) 1317 at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447) 1318 Failure in testSpinnerUI: 1319 junit.framework.ComparisonFailure: expected:<Result> but was:<Saturn> 1320 at com.android.example.spinner.test.SpinnerActivityTest.testSpinnerUI(SpinnerActivityTest.java:153) 1321 at java.lang.reflect.Method.invokeNative(Native Method) 1322 at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205) 1323 at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195) 1324 at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:175) 1325 at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) 1326 at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) 1327 at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430) 1328 at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447) 1329 .. 1330 Test results for InstrumentationTestRunner=.F.F.. 1331 Time: 9.377 1332 FAILURES!!! 1333 Tests run: 4, Failures: 2, Errors: 0 1334 </pre> 1335