Android Test (eight): UI Automator Automated Testing
Release date December 20, 2017 bug Master
Original: https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html
User interface (UI) tests that involve user interaction across multiple applications can validate an application's behavior when user traffic crosses other applications or enters the system UI. An example of this user process is a messaging application that allows the user to enter a text message, launch the Android contact selector so that the user can select the recipient to send a message, and then return control to the user's original application and submit the message.
This section describes how to write such UI tests using the UI Automator test framework provided by the Android test Support library. The UI Automator API allows you to interact with visible elements on your device, regardless of which activity is in focus. Your test can find the UI component with a handy descriptor, such as the text displayed in the component or its content description. The UI Automator test can run on devices running Android 4.3 (API level 18) or later.
The UI Automator test framework is a instrumentation-based API and is used with the Androidjunitrunner test Runner.
Set UI Automator
Before you build your UI tests using UI Automator, be sure to configure the test source code location and project dependencies as described in the previous section.
In the Build.gradle file of the Android application module, you must set up a dependency reference to the UI Automator Library:
‘com.android.support.test.uiautomator:uiautomator-v18:2.1.1‘}
To optimize your UI Automator testing, you should first check the UI components of the target application and make sure they are accessible. These optimization techniques are described in the following two sections.
Viewing the UI on a device
Before you design your tests, examine the UI components that are visible on the device. To ensure that your UI Automator tests can access these components, check to see if they have visible text labels, android:contentDescription
values.
The Uiautomatorviewer tool provides a convenient visual interface to examine the layout hierarchy and to view the properties of the UI components visible in the foreground of the device. This information allows you to create more granular tests using the UI Automator. For example, you can create a UI selector that matches a specific visible property.
To start the Uiautomatorviewer tool:
1. Start the target application on the physical device.
2. Connect the device to your development machine.
3. Open the terminal window and navigate to the <android-sdk> / tools /
directory.
4. Run the tool using the following command:
$ uiautomatorviewer
To view the UI properties of your application:
1. In the Uiautomatorviewer interface, click the Device screensho button.
2. Hover over the snapshot in the left panel to view the UI components identified by the Uiautomatorviewer tool. The properties are listed in the lower right panel, at the top right of the layout hierarchy.
3. Alternatively, click the Toggle NAF Nodes button to view UI components that the UI Automator cannot access. Only limited information is available for these components.
Make sure your activity is accessible
The UI Automator Test framework performs better for applications that have implemented Android accessibility. When you use a view-type UI element or a subclass of view in the SDK or support library, you do not need to implement accessibility support, because these classes are already done for you.
However, some applications use custom UI elements to provide a richer user experience. These elements do not provide automatic accessibility support. If your application contains instances of view subclasses that are not from the SDK or the support library, make sure that you add accessibility features to these elements by completing the following steps:
1. Create a ExploreByTouchHelper
specific class for the extension.
2. Associate an setAccessibilityDelegate()
instance of a new class with a specific custom UI element by calling it.
For additional guidance on adding accessibility features to Custom view elements, see Building accessible Custom views for more information about general best practices for accessibility on Android, see making applications easier to access.
Create a UI Automator test class
The UI Automator test class should be written just like the JUnit 4 test class. To learn more about creating JUnit 4 test classes and using JUnit 4 assertions and annotations, see Creating Test Unit Test classes.
Add a comment at the beginning of the test class definition @RunWith(AndroidJUnit4.class)
. You will also need to designate the Androidjunitrunner class provided in the Android test support library as your default test runner. This step is described in more detail in running a UI Automator test on a device or emulator.
Implement the following programming model in the UI Automator Test class:
1. getInstance()
get an UiDevice
object to access the device you want to test by calling the method and passing a instrumentation object as a parameter.
2. By invoking the findObject()
method, get UiObject
the object to access the UI component displayed on the device (for example, the current view in the foreground).
3. By invoking a UiObject
method to simulate a specific user interaction to execute on that UI component, for example, a call performMultiPointerGesture()
to simulate a multi-touch gesture to setText()
edit a text field. You can repeatedly invoke the APIs in steps 2 and 3 as needed to test for more complex user interactions involving multiple UI components or sequences of user actions.
4. After performing these user interactions, check that the UI reflects the expected state or behavior.
These steps are described in detail in the following sections.
Accessing the UI Component
The Uidevice object is the primary way to access and manipulate device state. The method is called in the test UiDevice
to check the state of various properties, such as the current direction or display size. You can use UiDevice
objects to perform device-level operations, such as forcing the device into a specific rotation state, pressing the D-PAD hardware button, and then pressing the home (home) and Menu buttons.
It's a good practice to start testing from your device's home screen. From the home screen (or another location selected on the device), you can invoke the methods provided by the UI Automator API to select and interact with specific UI elements.
The following code snippet shows how the test gets an UiDevice
instance and simulates pressing a home button:
Import Org.junit.Before;Import ANDROID.SUPPORT.TEST.RUNNER.ANDROIDJUNIT4;Import Android.support.test.uiautomator.UiDevice;Import Android.support.test.uiautomator.By;Import Android.support.test.uiautomator.Until, .....@RunWith (Androidjunit4.class)@SdkSuppress (minsdkversion =18)PublicClasschangetextbehaviortest {PrivateStaticFinal String basic_sample_package ="Com.example.android.testing.uiautomator.BasicSample";PrivateStaticFinalint launch_timeout =5000;PrivateStaticFinal String string_to_be_typed ="Uiautomator";Private Uidevice Mdevice;@BeforePublicvoidStartmainactivityfromhomescreen() {Initialize Uidevice Instance Mdevice = Uidevice.getinstance (Instrumentationregistry.getinstrumentation ());Start from the Home Screen Mdevice.presshome ();Wait for LauncherFinal String launcherpackage = Mdevice.getlauncherpackagename (); Assertthat (Launcherpackage, Notnullvalue ()); Mdevice.wait (Until.hasobject (by.pkg (launcherpackage) Depth (0)), launch_timeout);//Launch the app Context context = Instrumentationregistry.getcontext (); final Intent Intent = Context.getpackagemanager () Getlaunchintentforpackage (basic_ Sample_package); //Clear out any previous instances & nbsp Intent.addflags (intent.flag_activity_clear_task); context.startactivity (intent); //Wait for the app to appear MDEVICE.WA It (Until.hasobject (by.pkg (basic_sample_package) Depth (0), launch_timeout); }}
In the example, the @SdkSuppress(minSdkVersion = 18)
statement helps ensure that the test runs only on Android 4.3 (API level 18) or higher, as required by the UI Automator framework.
Use the findObject()
method to retrieve one UiObject
, which represents a view that matches a given selector condition. Reuse instances created in other parts of the application test as needed UIObject
. Note that each time a test uses a UIObject instance to click a UI element or query property, the UI Automator test framework searches for a match in the current display.
The following fragment shows how the test builds an instance that represents the Cancel button and the OK button in the application UIObject
.
UiObject cancelButton = mDevice.findObject(new UiSelector() .text("Cancel")) .className("android.widget.Button"));UiObject okButton = mDevice.findObject(new UiSelector() .text("OK")) .className("android.widget.Button"));// Simulate a user-click on the OK button, if found.if(okButton.exists() && okButton.isEnabled()) { okButton.click();}
Specifying selectors
If you want to access specific UI components in your application, use a UiSelector
class. This class represents a query for a specific element in the currently displayed UI.
If more than one matching element is found, the first matching element in the hierarchy is returned as a target UiObject
. When you build UiSelector
, you can link multiple properties together to refine your search. Thrown if no matching UI element is found UiAutomatorObjectNotFoundException
.
You can use childSelector()
methods to nest multiple UiSelector
instances. For example, the following code example shows how to test the search to find the first in the currently displayed UI ListView
, and then ListView
search within that to find UI elements with text attribute apps.
new UiObject(new UiSelector() .className("android.widget.ListView") .instance(0) .childSelector(new UiSelector() .text("Apps")));
As a best practice, when you specify a selector, you should use a resource ID (if you assign it to a UI element) instead of a text element or a content descriptor. Not all elements have text elements (for example, icons in toolbars). The text selector is fragile and can cause a test to fail if the UI changes slightly. They may also not be able to cross different languages; Your text selector may not match the translated string.
Specifying the state of an object in a selector condition can be useful. For example, if you want to select a list of all selected elements so that they are unchecked, use the method with the parameter set to True checked()
.
Perform actions
Once your test has acquired an UIObject
object, you can invoke a method in the UIObject
class to perform user interaction on the UI component that the object represents. Specify the following actions:
Click (): clicks the center of the visible boundary of the UI element.
Dragto (): Drag this object to any coordinate.
SetText (): Sets the text in the editable field after the contents of the field are cleared. Instead, the Cleartextfield () method clears the existing text in the editable field.
Swipeup (): Performs a slide operation on the UIObject. Similarly, the Swipedown (), Swipeleft (), and Swiperight () methods also perform appropriate operations.
The UI Automator Test Framework allows you getContext()
to send intent or initiate an activity by acquiring a context object without using a shell command.
The following fragment shows how the test uses intent to launch the application in the test. This method is useful when you are just interested in testing the Calculator application and do not care about the launcher.
public void setUp() { ... // Launch a simple calculator app Context context = getInstrumentation().getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(CALC_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT);}
To perform an action on a collection
If you want to simulate user interaction on a project collection (for example, a song in a music album or an email list in your inbox), use a UiCollection
class. To create UiCollection
an object, specify a UiSelector
wrapper that searches the UI container or other child UI elements, such as a layout view that contains child UI elements.
The following code snippet shows how the test was built UiCollection
to represent FrameLayout
the video album displayed in:
Uicollection videos =New Uicollection (New Uiselector (). ClassName ("Android.widget.FrameLayout"));Retrieve the number of videos in this collection:int count = Videos.getchildcount (new Uiselector (). ClassName ("android.widget.LinearLayout")); Find a specific video and simulate a user-click on ituiobject video = Videos.getchildbytext (new Uiselector () . ClassName ("Android.widget.LinearLayout"), "Cute Baby Laughing"); Video.click (); Simulate selecting a checkbox that's associated with the Videouiobject checkbox = Video.getchild (new Uiselector () . ClassName ("Android.widget.Checkbox")); if (!checkbox.isselected ()) Checkbox.click ();
To perform an action on a scrollable view
Use the UiScrollable
class to simulate a vertical or horizontal scrolling display. This technique is useful when the UI element is outside the screen and needs to be scrolled to display it in the view.
The following code snippet shows how to simulate scrolling down the "Settings" menu and clicking on "About Tablet option":
new UiScrollable(new UiSelector() .className("android.widget.ListView"));UiObject about = settingsItem.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "About tablet");about.click();
Validation results
Instrumentationtestcase extends the testcase, so you can use the standard JUnit Assert
method to test the UI components in your application to return the expected results.
The following fragment shows how to find several buttons in the Calculator application, click them sequentially, and then verify that the correct results are displayed.
PrivateStaticFinal String calc_package ="Com.myexample.calc";PublicvoidTesttwoplusthreeequalsfive() {Enter an Equation:2 + 3 =? Mdevice.findobject (New Uiselector (). PackageName (Calc_package). ResourceId (new uiselector () PackageName (calc_package) resourceId ( "plus"). Click (); Mdevice.findobject (new uiselector () PackageName ( calc_package). ResourceId (new uiselector () . PackageName (Calc_package). ResourceId ( "equals"). Click (); //Verify The result = 5 UiObject result = Mdevice.findobject (By.res (calc_package, "result")); Assertequals ( "5", Result.gettext ());}
Run the UI Automator test on a device or emulator
You can run UI Automator tests from Android Studio or from the command line. Make sure that Androidjunitrunner is specified as the default detection tool in the project.
To run the UI Automator test, run the test as described in the previous section.
Android Test (eight): UI Automator Automated Testing