1page.title=Testing UI for Multiple Apps 2page.tags=testing,ui automator 3trainingnavtop=true 4 5@jd:body 6 7<!-- This is the training bar --> 8<div id="tb-wrapper"> 9<div id="tb"> 10 <h2>Dependencies and Prerequisites</h2> 11 12 <ul> 13 <li>Android 4.3 (API level 18) or higher</li> 14 <li><a href="{@docRoot}tools/testing-support-library/index.html"> 15 Android Testing Support Library</a></li> 16 </ul> 17 18 <h2>This lesson teaches you to</h2> 19 20 <ol> 21 <li><a href="#setup">Set Up UI Automator</a></li> 22 <li><a href="#build">Create a UI Automator Test Class</a></li> 23 <li><a href="#run">Run UI Automator Tests on a Device or Emulator</a></li> 24 </ol> 25 26 <h2>You should also read</h2> 27 28 <ul> 29 <li><a href="{@docRoot}reference/android/support/test/package-summary.html"> 30UI Automator API Reference</a></li> 31 </ul> 32 33 <h2>Try it out</h2> 34 35 <ul> 36 <li><a href="https://github.com/googlesamples/android-testing" 37class="external-link">UI Automator Code Samples</a></li> 38 </ul> 39</div> 40</div> 41 42<p>A user interface (UI) test that involves user interactions across multiple apps lets you 43verify that your app behaves correctly when the user flow crosses into other apps or into the 44system UI. An example of such a user flow is a messaging app that lets the user enter a text 45message, launches the Android contact picker so that the users can select recipients to send the 46message to, and then returns control to the original app for the user to submit the message.</p> 47 48<p>This lesson covers how to write such UI tests using the 49UI Automator testing framework provided by the 50<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>. 51The UI Automator APIs let you interact with visible elements on a device, regardless of 52which {@link android.app.Activity} is in focus. Your test can look up a UI component by using 53convenient descriptors such as the text displayed in that component or its content description. UI 54Automator tests can run on devices running Android 4.3 (API level 18) or higher.</p> 55 56<p>The UI Automator testing framework is an instrumentation-based API and works 57with the 58<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html"> 59 {@code AndroidJUnitRunner}</a> 60test runner. 61</p> 62 63<h2 id="setup">Set Up UI Automator</h2> 64<p>Before you begin using UI Automator, you must:</p> 65 66 <ul> 67 <li> 68 <strong>Install the Android Testing Support Library</strong>. The UI Automator API is 69 located under the {@code com.android.support.test.uiautomator} package. These classes allow 70 you to create tests that use the Espresso testing framework. To learn how to install the 71 library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup"> 72 Testing Support Library Setup</a>. 73 </li> 74 75 <li> 76 <strong>Set up your project structure.</strong> In your Gradle project, the source code for 77 the target app that you want to test is typically placed under the {@code app/src/main} 78 folder. The source code for instrumentation tests, including 79 your UI Automator tests, must be placed under the <code>app/src/androidTest</code> folder. 80 To learn more about setting up your project directory, see 81 <a href="{@docRoot}tools/projects/index.html">Managing Projects</a>. 82 </li> 83 84 <li> 85 <strong>Specify your Android testing dependencies</strong>. In order for the 86 <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to 87 correctly build and run your UI Automator tests, you must specify the following libraries in 88 the {@code build.gradle} file of your Android app module: 89 90 <pre> 91dependencies { 92 androidTestCompile 'com.android.support.test:runner:0.3' 93 androidTestCompile 'com.android.support.test:rules:0.3' 94 androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1' 95} 96</pre> 97 </li> 98 </ul> 99 100<p>To optimize your UI Automator testing, you should first inspect the target app’s UI components 101and ensure that they are accessible. These optimization tips are described in the next two 102sections.</p> 103 104<h3 id="inspecting-ui">Inspecting the UI on a device</h3> 105<p>Before designing your test, inspect the UI components that are visible on the device. To 106ensure that your UI Automator tests can access these components, check that these components 107have visible text labels, 108<a href="http://developer.android.com/reference/android/view/View.html#attr_android:contentDescription"> 109{@code android:contentDescription}</a> 110values, or both.</p> 111 112<p>The {@code uiautomatorviewer} tool provides a convenient visual interface to inspect the layout 113hierarchy and view the properties of UI components that are visible on the foreground of the device. 114This information lets you create more fine-grained tests using UI Automator. For example, you can 115create a UI selector that matches a specific visible property. </p> 116 117<p>To launch the {@code uiautomatorviewer} tool:</p> 118 119<ol> 120 <li>Launch the target app on a physical device.</li> 121 <li>Connect the device to your development machine.</li> 122 <li>Open a terminal window and navigate to the {@code <android-sdk>/tools/} directory.</li> 123 <li>Run the tool with this command: 124<pre>$ uiautomatorviewer</pre> 125 </li> 126</ol> 127 128<p>To view the UI properties for your application:</p> 129 130<ol> 131 <li>In the {@code uiautomatorviewer} interface, click the <strong>Device Screenshot</strong> 132button.</li> 133 <li>Hover over the snapshot in the left-hand panel to see the UI components identified by the 134{@code uiautomatorviewertool}. The properties are listed in the lower right-hand panel and the 135layout hierarchy in the upper right-hand panel.</li> 136 <li>Optionally, click on the <strong>Toggle NAF Nodes</strong> button to see UI components that 137are non-accessible to UI Automator. Only limited information may be available for these 138components.</li> 139</ol> 140 141<p>To learn about the common types of UI components provided by Android, see 142<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>.</p> 143 144<h3>Ensuring your Activity is accessible</h3> 145<p>The UI Automator test framework depends on the accessibility features of the Android framework 146to look up individual UI elements. As a developer, you should implement these minimum 147optimizations in your {@link android.app.Activity} to support UI Automator:</p> 148 149<ul> 150<li>Use the 151<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription"> 152 {@code android:contentDescription}</a> 153attribute to label the {@link android.widget.ImageButton}, {@link android.widget.ImageView}, 154{@link android.widget.CheckBox} and other user interface controls.</li> 155<li>Provide an <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a> 156attribute instead of a content description for {@link android.widget.EditText} fields.</li> 157<li>Associate an <a href="http://developer.android.com/reference/android/widget/TextView.html#attr_android:hint"> 158 {@code android:hint}</a> 159attribute with any graphical icons used by controls that provide feedback to the user 160(for example, status or state information).</li> 161<li>Use the {@code uiautomatorviewer} tool to ensure that the UI component is accessible to the 162testing framework. You can also test the application by turning on accessibility services like 163TalkBack and Explore by Touch, and try using your application using only directional controls.</li> 164</ul> 165 166<p>Generally, app developers get accessibility support for free, courtesy of 167the {@link android.view.View} and {@link android.view.ViewGroup} 168classes. However, some apps use custom view elements to provide a richer user experience. Such 169custom elements won't get the accessibility support that is provided by the standard Android UI 170elements. If this applies to your app, make sure that it exposes the custom-drawn UI element to 171Android accessibility services by implementing the 172{@link android.view.accessibility.AccessibilityNodeProvider} class.</p> 173 174<p>If the custom view element contains a single element, make it accessible by 175<a href="{@docRoot}guide/topics/ui/accessibility/apps.html#accessibility-methods">implementing 176accessibility API methods</a>. 177If the custom view contains elements that are not views themselves (for example, a 178{@link android.webkit.WebView}, make sure it implements the 179{@link android.view.accessibility.AccessibilityNodeProvider} class. For container views that 180extend an existing container implementation 181(for example, a {@link android.widget.ListView}), implementing 182{@link android.view.accessibility.AccessibilityNodeProvider} is not necessary.</p> 183 184<p>For more information about implementing and testing accessibility, see 185<a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>.</p> 186 187<h2 id="build">Create a UI Automator Test Class</h2> 188 189<p>To build a UI Automator test, create a class that extends 190{@link android.test.InstrumentationTestCase}. Implement the following programming model in your 191UI Automator test class:</p> 192 193<ol> 194<li>Get a 195 <a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a> 196 object to access the device you want to test, by calling the 197<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#getInstance(android.app.Instrumentation)"> 198{@code getInstance()}</a> 199method and passing it an {@link android.app.Instrumentation} object as the argument.</li> 200<li>Get a 201<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 202object to access a UI component that is displayed on the device 203 (for example, the current view in the foreground), by calling the 204<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)"> 205 {@code findObject()}</a> 206method. 207</li> 208<li>Simulate a specific user interaction to perform on that UI component, by calling a 209<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 210method; for example, call 211<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#performMultiPointerGesture(android.view.MotionEvent.PointerCoords[]...)"> 212 {@code performMultiPointerGesture()}</a> 213to simulate a multi-touch gesture, and 214<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)">{@code setText()}</a> 215to edit a text field. You can call on the APIs in steps 2 and 3 repeatedly as necessary to test 216more complex user interactions that involve multiple UI components or sequences of user actions.</li> 217<li>Check that the UI reflects the expected state or behavior, after these user interactions are 218 performed. </li> 219</ol> 220 221<p>These steps are covered in more detail in the sections below.</p> 222 223<h3 id="accessing-ui-components">Accessing UI Components</h3> 224<p>The 225<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a> 226 object is the primary way you access and manipulate the state of the 227device. In your tests, you can call 228<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a> 229methods to check for the state of various properties, such as current orientation or display size. 230Your test can use the 231<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a> 232object to perform device-level actions, such as forcing the device into a specific rotation, 233pressing D-pad hardware buttons, and pressing the Home and Menu buttons.</p> 234 235<p>It’s good practice to start your test from the Home screen of the device. From the Home screen 236(or some other starting location you’ve chosen in the device), you can call the methods provided by 237the UI Automator API to select and interact with specific UI elements. </p> 238 239<p>The following code snippet shows how your test might get an instance of 240<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a> 241and simulate a Home button press:</p> 242 243<pre> 244import android.test.InstrumentationTestCase; 245import android.support.test.uiautomator.UiDevice; 246import android.support.test.uiautomator.By; 247 248public class CalculatorUiTest extends InstrumentationTestCase { 249 250 private UiDevice mDevice; 251 252 public void setUp() { 253 // Initialize UiDevice instance 254 mDevice = UiDevice.getInstance(getInstrumentation()); 255 256 // Start from the home screen 257 mDevice.pressHome(); 258 mDevice.wait(Until.hasObject(By.pkg(getHomeScreenPackage()).depth(0)), 259 } 260} 261</pre> 262 263<p>Use the 264<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)">{@code findObject()}</a> 265method to retrieve a 266<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 267which represents a view that matches a given selector criteria. You can reuse the 268<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 269instances that you have created in other parts of your app testing, as needed. Note that the 270UI Automator test framework searches the current display for a match every time your test uses a 271<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 272instance to click on a UI element or query a property.</p> 273 274<p>The following snippet shows how your test might construct 275<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 276instances that represent a Cancel button and a OK button in an app.</p> 277 278<pre> 279UiObject cancelButton = mDevice.findObject(new UiSelector() 280 .text("Cancel")) 281 .className("android.widget.Button")); 282UiObject okButton = mDevice.findObject(new UiSelector() 283 .text("OK")) 284 .className("android.widget.Button")); 285 286// Simulate a user-click on the OK button, if found. 287if(okButton.exists() && okButton.isEnabled()) { 288 okButton.click(); 289} 290</pre> 291 292<h4 id="specifying-selector">Specifying a selector</h4> 293<p>If you want to access a specific UI component in an app, use the 294<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a> 295class. This class represents a query for specific elements in the 296currently displayed UI. </p> 297 298<p>If more than one matching element is found, the first matching element in the layout hierarchy 299is returned as the target 300<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>. 301When constructing a 302<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>, 303you can chain together multiple properties to refine your search. If no matching UI element is 304found, a 305<a href="{@docRoot}reference/android/support/test/uiautomator/UiObjectNotFoundException.html"> 306{@code UiAutomatorObjectNotFoundException}</a> is thrown. </p> 307 308<p>You can use the 309<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html#childSelector(android.support.test.uiautomator.UiSelector)">{@code childSelector()}</a> 310method to nest multiple 311<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a> 312instances. For example, the following code example shows how your test might specify a search to 313find the first {@link android.widget.ListView} in the currently displayed UI, then search within that 314{@link android.widget.ListView} to find a UI element with the text property Apps.</p> 315 316<pre> 317UiObject appItem = new UiObject(new UiSelector() 318 .className("android.widget.ListView") 319 .instance(1) 320 .childSelector(new UiSelector() 321 .text("Apps"))); 322</pre> 323 324<p>As a best practice, when specifying a selector, you should use a Resource ID (if one is assigned 325to a UI element) instead of a text element or content-descriptor. Not all elements have a text 326element (for example, icons in a toolbar). Text selectors are brittle and can lead to test failures 327if there are minor changes to the UI. They may also not scale across different languages; your text 328selectors may not match translated strings.</p> 329 330<p>It can be useful to specify the object state in your selector criteria. For example, if you want 331to select a list of all checked elements so that you can uncheck them, call the 332<a href="{@docRoot}reference/android/support/test/uiautomator/By.html#checked(boolean)"> 333{@code checked()}</a> 334method with the argument set to {@code true}.</p> 335 336<h3 id="performing-actions">Performing Actions</h3> 337 338<p>Once your test has obtained a 339<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 340object, you can call the methods in the 341<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a> 342class to perform user interactions on the UI component represented by that 343object. You can specify such actions as:</p> 344 345<ul> 346<li> 347<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#click()"> 348 {@code click()}</a> 349: Clicks the center of the visible bounds of the UI element.</li> 350<li> 351<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#dragTo(int, int, int)"> 352 {@code dragTo()}</a> 353: Drags this object to arbitrary coordinates.</li> 354<li> 355<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)"> 356 {@code setText()}</a> 357: Sets the text in an editable field, after clearing the field's content. 358Conversely, the 359<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#clearTextField()"> 360 {@code clearTextField()}</a> 361method clears the existing text in an editable field.</li> 362<li> 363<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeUp(int)"> 364 {@code swipeUp()}</a> 365: Performs the swipe up action on the 366<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>. 367Similarly, the 368<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeDown(int)"> 369 {@code swipeDown()}</a>, 370<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeLeft(int)"> 371 {@code swipeLeft()}</a>, and 372<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeRight(int)"> 373 {@code swipeRight()}</a> 374methods perform corresponding actions.</li> 375</ul> 376 377<p>The UI Automator testing framework allows you to send an 378{@link android.content.Intent} 379or launch an {@link android.app.Activity} 380without using shell commands, by getting a 381{@link android.content.Context} 382object through 383{@link android.app.Instrumentation#getContext() getContext()}.</p> 384 385<p>The following snippet shows how your test can use an 386{@link android.content.Intent} to launch the app under test. This approach is useful when you are 387only interested in testing the calculator app, and don't care about the launcher.</p> 388 389<pre> 390public void setUp() { 391 ... 392 393 // Launch a simple calculator app 394 Context context = getInstrumentation().getContext(); 395 Intent intent = context.getPackageManager() 396 .getLaunchIntentForPackage(CALC_PACKAGE); 397 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 398 // Clear out any previous instances 399 context.startActivity(intent); 400 mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT); 401} 402</pre> 403 404<h4 id="actions-on-collections">Performing actions on collections</h4> 405 406<p>Use the 407<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html"> 408 {@code UiCollection}</a> 409class if you want to simulate user interactions on a 410collection of items (for example, songs in a music album or a list of emails in an Inbox). To 411create a 412<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html"> 413 {@code UiCollection}</a> 414object, specify a 415<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a> 416that searches for a 417UI container or a wrapper of other child UI elements, such as a layout view that contains child UI 418elements.</p> 419 420<p>The following code snippet shows how your test might construct a 421<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html"> 422 {@code UiCollection}</a> 423to represent a video album that is displayed within a {@link android.widget.FrameLayout}:</p> 424 425<pre> 426UiCollection videos = new UiCollection(new UiSelector() 427 .className("android.widget.FrameLayout")); 428 429// Retrieve the number of videos in this collection: 430int count = videos.getChildCount(new UiSelector() 431 .className("android.widget.LinearLayout")); 432 433// Find a specific video and simulate a user-click on it 434UiObject video = videos.getChildByText(new UiSelector() 435 .className("android.widget.LinearLayout"), "Cute Baby Laughing"); 436video.click(); 437 438// Simulate selecting a checkbox that is associated with the video 439UiObject checkBox = video.getChild(new UiSelector() 440 .className("android.widget.Checkbox")); 441if(!checkBox.isSelected()) checkbox.click(); 442</pre> 443 444<h4 id="actions-on-scrollable-views">Performing actions on scrollable views</h4> 445<p>Use the 446<a href="{@docRoot}reference/android/support/test/uiautomator/UiScrollable.html"> 447 {@code UiScrollable}</a> 448class to simulate vertical or horizontal scrolling across a display. This technique is helpful when 449a UI element is positioned off-screen and you need to scroll to bring it into view.</p> 450 451<p>The following code snippet shows how to simulate scrolling down the Settings menu and clicking 452on an About tablet option:</p> 453 454<pre> 455UiScrollable settingsItem = new UiScrollable(new UiSelector() 456 .className("android.widget.ListView")); 457UiObject about = settingsItem.getChildByText(new UiSelector() 458 .className("android.widget.LinearLayout"), "About tablet"); 459about.click(); 460</pre> 461 462<h3 id="verifying-results">Verifying Results</h3> 463<p>The {@link android.test.InstrumentationTestCase} extends {@link junit.framework.TestCase}, so 464you can use standard JUnit <a href="http://junit.org/javadoc/latest/org/junit/Assert.html" 465class="external-link">{@code Assert}</a> methods to test 466that UI components in the app return the expected results. </p> 467 468<p>The following snippet shows how your test can locate several buttons in a calculator app, click 469on them in order, then verify that the correct result is displayed.</p> 470 471<pre> 472private static final String CALC_PACKAGE = "com.myexample.calc"; 473 474public void testTwoPlusThreeEqualsFive() { 475 // Enter an equation: 2 + 3 = ? 476 mDevice.findObject(new UiSelector() 477 .packageName(CALC_PACKAGE).resourceId("two")).click(); 478 mDevice.findObject(new UiSelector() 479 .packageName(CALC_PACKAGE).resourceId("plus")).click(); 480 mDevice.findObject(new UiSelector() 481 .packageName(CALC_PACKAGE).resourceId("three")).click(); 482 mDevice.findObject(new UiSelector() 483 .packageName(CALC_PACKAGE).resourceId("equals")).click(); 484 485 // Verify the result = 5 486 UiObject result = mDevice.findObject(By.res(CALC_PACKAGE, "result")); 487 assertEquals("5", result.getText()); 488} 489</pre> 490 491<h2 id="run">Run UI Automator Tests on a Device or Emulator</h2> 492<p>UI Automator tests are based on the {@link android.app.Instrumentation} class. The 493<a href="https://developer.android.com/tools/building/plugin-for-gradle.html"> 494 Android Plug-in for Gradle</a> 495provides a default directory ({@code src/androidTest/java}) for you to store the instrumented test 496classes and test suites that you want to run on a device. The plug-in compiles the test 497code in that directory and then executes the test app using a test runner class. You are 498strongly encouraged to use the 499<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a> 500class provided in the 501<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a> 502as your default test runner. </p> 503 504<p>To run UI Automator tests in your Gradle project:</p> 505 506<ol> 507<li>Specify 508<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a> 509as the default test instrumentation runner in your {@code build.gradle} file: 510<pre> 511android { 512 defaultConfig { 513 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 514 } 515}</pre> 516</li> 517<li>Run your tests from the command-line by calling the {@code connectedCheck} 518 (or {@code cC}) task: 519<pre>./gradlew cC</pre> 520</li> 521</ol>