page.title=UI Testing parent.title=Testing parent.link=index.html @jd:body
In addition to unit testing the individual components that make up your Android application (such as activities, services, and content providers), it is also important that you test the behavior of your application’s user interface (UI) when it is running on a device. UI testing ensures that your application returns the correct UI output in response to a sequence of user actions on a device, such as entering keyboard input or pressing toolbars, menus, dialogs, images, and other UI controls.
Functional or black-box UI testing does not require testers to know the internal implementation details of the app, only its expected output when a user performs a specific action or enters a specific input. This approach allows for better separation of development and testing roles in your organization.
One common approach to UI testing is to run tests manually and verify that the app is behaving as expected. However, this approach can be time-consuming, tedious, and error-prone. A more efficient and reliable approach is to automate the UI testing with a software testing framework. Automated testing involves creating programs to perform testing tasks (test cases) to cover specific usage scenarios, and then using the testing framework to run the test cases automatically and in a repeatable manner.
The Android SDK provides the following tools to support automated, functional UI testing on your application:
To use these tools, you must have the following versions of the Android development tools installed:
Here's a short overview of the steps required to automate UI testing:
Before you start writing your test cases, it's helpful to familiarize yourself with the UI components (including the views and controls) of the targeted application. You can use the {@code uiautomatorviewer} tool to take a snapshot of the foreground UI screen on any Android device that is connected to your development machine. The {@code uiautomatorviewer} tool provides a convenient visual interface to inspect the layout hierarchy and view the properties of the individual UI components that are displayed on the test device. Using this information, you can later create {@code uiautomator} tests with selector objects that target specific UI components to test.
To analyze the UI components of the application that you want to test:
$ uiautomatorviewer
To capture a screen for analysis, click the Device Screenshot button in the GUI of the {@code uiautomatorviewer} tool.
Note: If you have more than one device connected, specify the device for screen capture by setting the {@code ANDROID_SERIAL} environment variable:
$ adb devices
set ANDROID_SERIAL=<device serial number>
export ANDROID_SERIAL=<device serial number>
Before using the {@code uiautomator} testing framework, complete these pre-flight tasks:
If you are reading this document, chances are that the Android application that you want to test has not been published yet. If you have a copy of the APK file, you can install the APK onto a test device by using the {@code adb} tool. To learn how to install an APK file using the {@code adb} tool, see the {@code adb} documentation.
Before writing your {@code uiautomator} tests, first identify the UI components in the application that you want to test. Typically, good candidates for testing are UI components that are visible and that users can interact with. The UI components should also have visible text labels, {@code android:contentDescription} values, or both.
You can inspect the visible screen objects in an application conveniently by using the {@code uiautomatorviewer} tool. For more information about how to analyze an application screen with this tool, see the section Analyzing Your Application’s UI. For more information about the common types of UI components provided by Android, see User Interface.
This step is required because the {@code uiautomator} tool depends on the accessibility features of the Android framework to execute your functional UI tests. You should include these minimum optimizations to support the {@code uiautomator} tool:
For more information about implementing and testing accessibility, see Making Applications Accessible.
Note: To identify the non-accessible components in the UI, click on the Toggle NAF Nodes option in the {@code uiautomatorviewer} tool.
Generally, Android application developers get accessibility support for free, courtesy of the {@link android.view.View} and {@link android.view.ViewGroup} classes. However, some applications use custom view components to provide a richer user experience. Such custom components won't get the accessibility support that is provided by the standard Android UI components. If this applies to your application, ensure that the application developer exposes the custom drawn UI components to Android accessibility services, by implementing the {@link android.view.accessibility.AccessibilityNodeProvider} class. For more information about making custom view components accessible, see Making Applications Accessible.
If you're developing in Eclipse, the Android SDK provides additional tools that help you write test cases using {@code uiautomator} and buiild your JAR file. In order to set up Eclipse to assist you, you need to create a project that includes the {@code uiautomator} client library, along with the Android SDK library. To configure Eclipse:
If you did not configure Eclipse as your development environment, make sure that the {@code uiautomator.jar} and {@code android.jar} files from the {@code <android-sdk>/platforms/<sdk>} directory are in your Java class path.
Once you have completed these prerequisite tasks, you're almost ready to start creating your {@code uiautomator} tests.
To build a test that runs in the {@code uiautomator} framework, create a test case that extends the {@code UiAutomatorTestCase} class. In Eclipse, the test case file goes under the {@code src} directory in your project. Later, you will build the test case as a JAR file, then copy this file to the test device. The test JAR file is not an APK file and resides separately from the application that you want to test on the device.
Because the {@code UiAutomatorTestCase} class extends {@code junit.framework.TestCase}, you can use the JUnit {@code Assert} class to test that UI components in the app return the expected results. To learn more about JUnit, you can read the documentation on the junit.org home page.
The first thing your test case should do is access the device that contains the target app. It’s also good practice to start the test from the Home screen of the device. From the Home screen (or some other starting location you’ve chosen in the target app), you can use the classes provided by the {@code uiautomator} API to simulate user actions and to test specific UI components. For an example of how to put together a {@code uiautomator} test case, see the sample test case.
The {@code uiautomator} API is bundled in the {@code uiautomator.jar} file under the {@code <android-sdk>/platforms/} directory. The API includes these key classes that allow you to capture and manipulate UI components on the target app:
Represents the device state. In your tests, you can call methods on the {@code UiDevice} instance to check for the state of various properties, such as current orientation or display size. Your tests also can use the {@code UiDevice} instance to perform device level actions, such as forcing the device into a specific rotation, pressing the d-pad hardware button, or pressing the Home and Menu buttons.
To get an instance of {@code UiDevice} and simulate a Home button press:
getUiDevice().pressHome();
UiObject appItem = new UiObject(new UiSelector() .className("android.widget.ListView").instance(1) .childSelector(new UiSelector().text("Apps")));
The following code example shows how to construct {@code UiObject} instances that represent a Cancel button and a OK button in your application.
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")); UiObject okButton = new UiObject(new UiSelector().text("OK"));
You can reuse the {@code UiObject} instances that you have created in other parts of your app testing, as needed. Note that the {@code uiautomator} test framework searches the current display for a match every time your test uses a {@code UiObject} instance to click on a UI element or query a property.
In the following code example, the {@code uiautomator} test framework searches for a UI element with the text property {@code OK}. If a match is found and if the element is enabled, the framework simulates a user click action on the element.
if(okButton.exists() && okButton.isEnabled()) { okButton.click(); }
You can also restrict the search to find only elements of a specific class. For example, to find matches of the {@link android.widget.Button} class:
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel") .className("android.widget.Button")); UiObject okButton = new UiObject(new UiSelector().text("OK") .className("android.widget.Button"));
UiCollection videos = new UiCollection(new UiSelector() .className("android.widget.FrameLayout"));
If the videos are listed within a {@link android.widget.LinearLayout} view, and you want to to retrieve the number of videos in this collection:
int count = videos.getChildCount(new UiSelector() .className("android.widget.LinearLayout"));
If you want to find a specific video that is labeled with the text element {@code Cute Baby Laughing} from the collection and simulate a user-click on the video:
UiObject video = videos.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "Cute Baby Laughing"); video.click();
Similarly, you can simulate other user actions on the UI object. For example, if you want to simulate selecting a checkbox that is associated with the video:
UiObject checkBox = video.getChild(new UiSelector() .className("android.widget.Checkbox")); if(!checkBox.isSelected()) checkbox.click();
For example, the following code shows how to simulate scrolling down the Settings menu and clicking on an About tablet option:
UiScrollable settingsItem = new UiScrollable(new UiSelector() .className("android.widget.ListView")); UiObject about = settingsItem.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "About tablet"); about.click()
For more information about these APIs, see the {@code uiautomator} reference.
The following code example shows a simple test case which simulates a user bringing up the Settings app in a stock Android device. The test case mimics all the steps that a user would typically take to perform this task, including opening the Home screen, launching the All Apps screen, scrolling to the Settings app icon, and clicking on the icon to enter the Settings app.
package com.uia.example.my; // Import the uiautomator libraries import com.android.uiautomator.core.UiObject; import com.android.uiautomator.core.UiObjectNotFoundException; import com.android.uiautomator.core.UiScrollable; import com.android.uiautomator.core.UiSelector; import com.android.uiautomator.testrunner.UiAutomatorTestCase; public class LaunchSettings extends UiAutomatorTestCase { public void testDemo() throws UiObjectNotFoundException { // Simulate a short press on the HOME button. getUiDevice().pressHome(); // We’re now in the home screen. Next, we want to simulate // a user bringing up the All Apps screen. // If you use the uiautomatorviewer tool to capture a snapshot // of the Home screen, notice that the All Apps button’s // content-description property has the value “Apps”. We can // use this property to create a UiSelector to find the button. UiObject allAppsButton = new UiObject(new UiSelector() .description("Apps")); // Simulate a click to bring up the All Apps screen. allAppsButton.clickAndWaitForNewWindow(); // In the All Apps screen, the Settings app is located in // the Apps tab. To simulate the user bringing up the Apps tab, // we create a UiSelector to find a tab with the text // label “Apps”. UiObject appsTab = new UiObject(new UiSelector() .text("Apps")); // Simulate a click to enter the Apps tab. appsTab.click(); // Next, in the apps tabs, we can simulate a user swiping until // they come to the Settings app icon. Since the container view // is scrollable, we can use a UiScrollable object. UiScrollable appViews = new UiScrollable(new UiSelector() .scrollable(true)); // Set the swiping mode to horizontal (the default is vertical) appViews.setAsHorizontalList(); // Create a UiSelector to find the Settings app and simulate // a user click to launch the app. UiObject settingsApp = appViews.getChildByText(new UiSelector() .className(android.widget.TextView.class.getName()), "Settings"); settingsApp.clickAndWaitForNewWindow(); // Validate that the package name is the expected one UiObject settingsValidation = new UiObject(new UiSelector() .packageName("com.android.settings")); assertTrue("Unable to detect Settings", settingsValidation.exists()); } }
Once you have coded your test, follow these steps to build and deploy your test JAR to your target Android test device:
<android-sdk>/tools/android create uitest-project -n <name> -t 1 -p <path>The {@code <name>} is the name of the project that contains your {@code uiautomator} test source files, and the {@code <path>} is the path to the corresponding project directory.
set ANDROID_HOME=<path_to_your_sdk>
export ANDROID_HOME=<path_to_your_sdk>
ant build
adb push <path_to_output_jar> /data/local/tmp/
Here’s an example:
adb push ~/dev/workspace/LaunchSettings/bin/LaunchSettings.jar /data/local/tmp/
Here’s an example of how to run a test that is implemented in the {@code LaunchSettings.jar} file. The tests are bundled in the {@code com.uia.example.my} package:
adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings
To learn more about the syntax, subcommands, and options for {@code uiautomator}, see the {@code uiautomator} reference.
Here are some best practices for functional UI testing with the {@code uiautomator} framework: