am d9e2c05d: am 0c3b894c: am 91070dc4: Merge "docs: Added training docs for UI testing frameworks (Espresso, UI Automator)." into lmp-docs
* commit 'd9e2c05dbf6c6f418b08a8465f1ed8f051015b41': docs: Added training docs for UI testing frameworks (Espresso, UI Automator).
This commit is contained in:
@@ -391,7 +391,9 @@ onView(withId(R.id.changeTextBt)).perform(click());</pre>
|
||||
|
||||
<p>
|
||||
To learn more about using Espresso, see the
|
||||
<a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a>.
|
||||
<a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a> and
|
||||
<a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">
|
||||
Testing UI for a Single App</a> training.
|
||||
</p>
|
||||
|
||||
<h3 id="UIAutomator">
|
||||
@@ -531,7 +533,9 @@ allAppsButton.clickAndWaitForNewWindow();</pre>
|
||||
|
||||
<p>
|
||||
To learn more about using UI Automator, see the
|
||||
<a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a>.
|
||||
<a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a> and
|
||||
<a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">
|
||||
Testing UI for Multiple Apps</a> training.
|
||||
</p>
|
||||
|
||||
<h2 id="setup">
|
||||
|
||||
579
docs/html/training/testing/ui-testing/espresso-testing.jd
Normal file
579
docs/html/training/testing/ui-testing/espresso-testing.jd
Normal file
@@ -0,0 +1,579 @@
|
||||
page.title=Testing UI for a Single App
|
||||
page.tags=testing,espresso
|
||||
trainingnavtop=true
|
||||
|
||||
@jd:body
|
||||
|
||||
<!-- This is the training bar -->
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dependencies and Prerequisites</h2>
|
||||
|
||||
<ul>
|
||||
<li>Android 2.2 (API level 8) or higher
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support
|
||||
Library</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
This lesson teaches you to
|
||||
</h2>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#setup">Set Up Espresso</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#build">Create an Espresso Test Class</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#run">Run Espresso Tests on a Device or Emulator</a>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h2>
|
||||
You should also read
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="{@docRoot}reference/android/support/test/package-summary.html">
|
||||
Espresso API Reference</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Try it out
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/googlesamples/android-testing"
|
||||
class="external-link">Espresso Code Samples</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
UI tests that involve user interactions
|
||||
within a single app help to ensure that users do not
|
||||
encounter unexpected results or have a poor experience when interacting with your app.
|
||||
You should get into the habit of creating user interface (UI) tests if you need to verify
|
||||
that the UI of your app is functioning correctly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Espresso testing framework, provided by the
|
||||
<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>,
|
||||
provides APIs for writing UI tests to simulate user interactions within a
|
||||
single target app. Espresso tests can run on devices running Android 2.2 (API level 8) and
|
||||
higher. A key benefit of using Espresso is that it provides automatic synchronization of test
|
||||
actions with the UI of the app you are testing. Espresso detects when the main thread is idle,
|
||||
so it is able to run your test commands at the appropriate time, improving the reliability of
|
||||
your tests. This capability also relieves you from having to adding any timing workarounds,
|
||||
such as a sleep period, in your test code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Espresso testing framework is an instrumentation-based API and works
|
||||
with the
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
|
||||
AndroidJUnitRunner}</a> test runner.
|
||||
</p>
|
||||
|
||||
<h2 id="setup">
|
||||
Set Up Espresso
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Before you begin using Espresso, you must:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Install the Android Testing Support Library</strong>. The Espresso API is
|
||||
located under the {@code com.android.support.test.espresso} package. These classes allow
|
||||
you to create tests that use the Espresso testing framework. To learn how to install the
|
||||
library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup">
|
||||
Testing Support Library Setup</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Set up your project structure.</strong> In your Gradle project, the source code for
|
||||
the target app that you want to test is typically placed under the {@code app/src/main}
|
||||
folder. The source code for instrumentation tests, including
|
||||
your Espresso tests, must be placed under the <code>app/src/androidTest</code> folder. To
|
||||
learn more about setting up your project directory, see
|
||||
<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Specify your Android testing dependencies</strong>. In order for the
|
||||
<a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to
|
||||
correctly build and run your Espresso tests, you must specify the following libraries in
|
||||
the {@code build.gradle} file of your Android app module:
|
||||
|
||||
<pre>
|
||||
dependencies {
|
||||
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
|
||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Turn off animations on your test device.</strong> Leaving system animations turned
|
||||
on in the test device might cause unexpected results or may lead your test to fail. Turn
|
||||
off animations from <em>Settings</em> by opening <em>Developing Options</em> and
|
||||
turning all the following options off:
|
||||
<ul>
|
||||
<li>
|
||||
<em>Window animation scale</em>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<em>Transition animation scale</em>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<em>Animator duration scale</em>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="build">
|
||||
Create an Espresso Test Class
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
To create an Espresso test, create a Java class or an
|
||||
{@link android.test.ActivityInstrumentationTestCase2}
|
||||
subclass that follows this programming model:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>Find the UI component you want to test in an {@link android.app.Activity} (for example, a
|
||||
sign-in button in the app) by calling the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a> method, or the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">
|
||||
{@code onData()}</a> method for {@link android.widget.AdapterView} controls.
|
||||
</li>
|
||||
|
||||
<li>Simulate a specific user interaction to perform on that UI component, by calling the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
|
||||
or
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
|
||||
method and passing in the user action (for example, click on the sign-in button). To sequence
|
||||
multiple actions on the same UI component, chain them using a comma-separated list in your
|
||||
method argument.
|
||||
</li>
|
||||
|
||||
<li>Repeat the steps above as necessary, to simulate a user flow across multiple
|
||||
activities in the target app.
|
||||
</li>
|
||||
|
||||
<li>Use the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
|
||||
methods to check that the UI reflects the expected
|
||||
state or behavior, after these user interactions are performed.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
These steps are covered in more detail in the sections below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following code snippet shows how your test class might invoke this basic workflow:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
onView(withId(R.id.my_view)) // withId(R.id.my_view) is a ViewMatcher
|
||||
.perform(click()) // click() is a ViewAction
|
||||
.check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
|
||||
</pre>
|
||||
|
||||
<h3 id="espresso-aitc2">
|
||||
Using Espresso with ActivityInstrumentationTestCase2
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
If you are subclassing {@link android.test.ActivityInstrumentationTestCase2}
|
||||
to create your Espresso test class, you must inject an
|
||||
{@link android.app.Instrumentation} instance into your test class. This step is required in
|
||||
order for your Espresso test to run with the
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
|
||||
test runner.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To do this, call the
|
||||
{@link android.test.InstrumentationTestCase#injectInstrumentation(android.app.Instrumentation) injectInstrumentation()}
|
||||
method and pass in the result of
|
||||
<a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html#getInstrumentation()">
|
||||
{@code InstrumentationRegistry.getInstrumentation()}</a>, as shown in the following code
|
||||
example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
||||
public class MyEspressoTest
|
||||
extends ActivityInstrumentationTestCase2<MyActivity> {
|
||||
|
||||
private MyActivity mActivity;
|
||||
|
||||
public MyEspressoTest() {
|
||||
super(MyActivity.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
|
||||
mActivity = getActivity();
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Previously, {@link android.test.InstrumentationTestRunner}
|
||||
would inject the {@link android.app.Instrumentation} instance, but this test runner is being
|
||||
deprecated.</p>
|
||||
|
||||
<h3 id="accessing-ui-components">
|
||||
Accessing UI Components
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Before Espresso can interact with the app under test, you must first specify the UI component
|
||||
or <em>view</em>. Espresso supports the use of
|
||||
<a href="http://hamcrest.org/" class="external-link">Hamcrest matchers</a>
|
||||
for specifying views and adapters in your app.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To find the view, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a>
|
||||
method and pass in a view matcher that specifies the view that you are targeting. This is
|
||||
described in more detail in <a href="#specifying-view-matcher">Specifying a View Matcher</a>.
|
||||
The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a> method returns a
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html">
|
||||
{@code ViewInteraction}</a>
|
||||
object that allows your test to interact with the view.
|
||||
However, calling the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a> method may not work if you want to locate a view in
|
||||
an {@link android.widget.AdapterView} layout. In this case, follow the instructions in
|
||||
<a href="#locating-adpeterview-view">Locating a view in an AdapterView</a> instead.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Note</strong>: The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a> method does not check if the view you specified is
|
||||
valid. Instead, Espresso searches only the current view hierarchy, using the matcher provided.
|
||||
If no match is found, the method throws a
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
|
||||
{@code NoMatchingViewException}</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following code snippet shows how you might write a test that accesses an
|
||||
{@link android.widget.EditText} field, enters a string of text, closes the virtual keyboard,
|
||||
and then performs a button click.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
public void testChangeText_sameActivity() {
|
||||
// Type text and then press the button.
|
||||
onView(withId(R.id.editTextUserInput))
|
||||
.perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard());
|
||||
onView(withId(R.id.changeTextButton)).perform(click());
|
||||
|
||||
// Check that the text was changed.
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4 id="specifying-view-matcher">
|
||||
Specifying a View Matcher
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
You can specify a view matcher by using these approaches:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Calling methods in the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html">
|
||||
{@code ViewMatchers}</a> class. For example, to find a view by looking for a text string it
|
||||
displays, you can call a method like this:
|
||||
<pre>
|
||||
onView(withText("Sign-in"));
|
||||
</pre>
|
||||
|
||||
<p>Similarly you can call
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html#withId(int)">
|
||||
{@code withId()}</a> and providing the resource ID ({@code R.id}) of the view, as shown in the
|
||||
following example:</p>
|
||||
|
||||
<pre>
|
||||
onView(withId(R.id.button_signin));
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Android resource IDs are not guaranteed to be unique. If your test attempts to match to a
|
||||
resource ID used by more than one view, Espresso throws an
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/AmbiguousViewMatcherException.html">
|
||||
{@code AmbiguousViewMatcherException}</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>Using the Hamcrest
|
||||
<a href="http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html"
|
||||
class="external-link">{@code Matchers}</a> class. You can use the
|
||||
{@code allOf()} methods to combine multiple matchers, such as
|
||||
{@code containsString()} and {@code instanceOf()}. This approach allows you to
|
||||
filter the match results more narrowly, as shown in the following example:
|
||||
<pre>
|
||||
onView(allOf(withId(R.id.button_signin), withText("Sign-in")));
|
||||
</pre>
|
||||
<p>You can use the {@code not} keyword to filter for views that don't correspond to the matcher, as
|
||||
shown in the following example:</p>
|
||||
<pre>
|
||||
onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
|
||||
</pre>
|
||||
<p>To use these methods in your test, import the {@code org.hamcrest.Matchers} package. To
|
||||
learn more about Hamcrest matching, see the
|
||||
<a href="http://hamcrest.org/" class="external-link">Hamcrest site</a>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
To improve the performance of your Espresso tests, specify the minimum matching information
|
||||
needed to find your target view. For example, if a view is uniquely identifiable by its
|
||||
descriptive text, you do not need to specify that it is also assignable from the
|
||||
{@link android.widget.TextView} instance.
|
||||
</p>
|
||||
|
||||
<h4 id="#locating-adpeterview-view">
|
||||
Locating a view in an AdapterView
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
In an {@link android.widget.AdapterView} widget, the view is dynamically populated with child
|
||||
views at runtime. If the target view you want to test is inside an
|
||||
{@link android.widget.AdapterView}
|
||||
(such as a {@link android.widget.ListView}, {@link android.widget.GridView}, or
|
||||
{@link android.widget.Spinner}), the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
|
||||
{@code onView()}</a> method might not work because only a
|
||||
subset of the views may be loaded in the current view hierarchy.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Instead, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
|
||||
method to obtain a
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html">
|
||||
{@code DataInteraction}</a>
|
||||
object to access the target view element. Espresso handles loading the target view element
|
||||
into the current view hierarchy. Espresso also takes care of scrolling to the target element,
|
||||
and putting the element into focus.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Note</strong>: The
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
|
||||
method does not check if if the item you specified corresponds with a view. Espresso searches
|
||||
only the current view hierarchy. If no match is found, the method throws a
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
|
||||
{@code NoMatchingViewException}</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following code snippet shows how you can use the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
|
||||
method together
|
||||
with Hamcrest matching to search for a specific row in a list that contains a given string.
|
||||
In this example, the {@code LongListActivity} class contains a list of strings exposed
|
||||
through a {@link android.widget.SimpleAdapter}.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
onData(allOf(is(instanceOf(Map.class)),
|
||||
hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));
|
||||
</pre>
|
||||
|
||||
<h3 id="perform-actions">
|
||||
Performing Actions
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Call the <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
|
||||
or
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
|
||||
methods to
|
||||
simulate user interactions on the UI component. You must pass in one or more
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
|
||||
objects as arguments. Espresso fires each action in sequence according to
|
||||
the given order, and executes them in the main thread.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html">{@code ViewActions}</a>
|
||||
class provides a list of helper methods for specifying common actions.
|
||||
You can use these methods as convenient shortcuts instead of creating and configuring
|
||||
individual <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
|
||||
objects. You can specify such actions as:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#click()">{@code ViewActions.click()}</a>:
|
||||
Clicks on the view.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#typeText(java.lang.String)">{@code ViewActions.typeText()}</a>:
|
||||
Clicks on a view and enters a specified string.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>:
|
||||
Scrolls to the view. The
|
||||
target view must be subclassed from {@link android.widget.ScrollView}
|
||||
and the value of its
|
||||
<a href="http://developer.android.com/reference/android/view/View.html#attr_android:visibility">{@code android:visibility}</a>
|
||||
property must be {@link android.view.View#VISIBLE}. For views that extend
|
||||
{@link android.widget.AdapterView} (for example,
|
||||
{@link android.widget.ListView}),
|
||||
the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
|
||||
method takes care of scrolling for you.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#pressKey(int)">{@code ViewActions.pressKey()}</a>:
|
||||
Performs a key press using a specified keycode.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#clearText()">{@code ViewActions.clearText()}</a>:
|
||||
Clears the text in the target view.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
If the target view is inside a {@link android.widget.ScrollView}, perform the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
|
||||
action first to display the view in the screen before other proceeding
|
||||
with other actions. The
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
|
||||
action will have no effect if the view is already displayed.
|
||||
</p>
|
||||
|
||||
<h3 id="verify-results">
|
||||
Verifying Results
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Call the
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code ViewInteraction.check()}</a>
|
||||
or
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code DataInteraction.check()}</a>
|
||||
method to assert
|
||||
that the view in the UI matches some expected state. You must pass in a
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/ViewAssertion.html">
|
||||
{@code ViewAssertion}</a> object as the argument. If the assertion fails, Espresso throws
|
||||
an {@link junit.framework.AssertionFailedError}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
|
||||
class provides a list of helper methods for specifying common
|
||||
assertions. The assertions you can use include:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#doesNotExist()">{@code doesNotExist}</a>:
|
||||
Asserts that there is no view matching the specified criteria in the current view hierarchy.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#matches(org.hamcrest.Matcher<? super android.view.View>)">{@code matches}</a>:
|
||||
Asserts that the specified view exists in the current view hierarchy
|
||||
and its state matches some given Hamcrest matcher.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#selectedDescendantsMatch(org.hamcrest.Matcher<android.view.View>, org.hamcrest.Matcher<android.view.View>)">{@code selectedDescendentsMatch}</a>
|
||||
: Asserts that the specified children views for a
|
||||
parent view exist, and their state matches some given Hamcrest matcher.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The following code snippet shows how you might check that the text displayed in the UI has
|
||||
the same value as the text previously entered in the
|
||||
{@link android.widget.EditText} field.
|
||||
</p>
|
||||
<pre>
|
||||
public void testChangeText_sameActivity() {
|
||||
// Type text and then press the button.
|
||||
...
|
||||
|
||||
// Check that the text was changed.
|
||||
onView(withId(R.id.textToBeChanged))
|
||||
.check(matches(withText(STRING_TO_BE_TYPED)));
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2 id="run">Run Espresso Tests on a Device or Emulator</h2>
|
||||
|
||||
<p>
|
||||
To run Espresso tests, you must use the
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
|
||||
class provided in the
|
||||
<a href="{@docRoot}tools/testing-support-library/index.html">
|
||||
Android Testing Support Library</a> as your default test runner. The
|
||||
<a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for
|
||||
Gradle</a> provides a default directory ({@code src/androidTest/java}) for you to store the
|
||||
instrumented test classes and test suites that you want to run on a device. The
|
||||
plug-in compiles the test code in that directory and then executes the test app using
|
||||
the configured test runner class.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To run Espresso tests in your Gradle project:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>Specify
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
|
||||
as the default test instrumentation runner in
|
||||
your {@code build.gradle} file:
|
||||
|
||||
<pre>
|
||||
android {
|
||||
defaultConfig {
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
}</pre>
|
||||
</li>
|
||||
<li>Run your tests from the command-line by calling the the {@code connectedCheck}
|
||||
(or {@code cC}) task:
|
||||
<pre>
|
||||
./gradlew cC</pre>
|
||||
</li>
|
||||
</ol>
|
||||
76
docs/html/training/testing/ui-testing/index.jd
Normal file
76
docs/html/training/testing/ui-testing/index.jd
Normal file
@@ -0,0 +1,76 @@
|
||||
page.title=Automating User Interface Tests
|
||||
page.tags=testing
|
||||
|
||||
trainingnavtop=true
|
||||
startpage=true
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>
|
||||
You should also read
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{@docRoot}/tools/testing-support-library/index.html">Testing Support Library</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>User interface (UI) testing lets you ensure that your app meets its functional requirements
|
||||
and achieves a high standard of quality such that it is more likely to be successfully adopted by
|
||||
users.</p>
|
||||
|
||||
<p>One approach to UI testing is to simply have a human tester perform a set of user operations on
|
||||
the target app and verify that it is behaving correctly. However, this manual approach can be
|
||||
time-consuming, tedious, and error-prone. A more efficient approach is to write your UI
|
||||
tests such that user actions are performed in an automated way. The automated approach allows
|
||||
you to run your tests quickly and reliably in a repeatable manner.</p>
|
||||
|
||||
<p class="note"><strong>Note: </strong>It is strongly encouraged that you use
|
||||
<a href="{@docRoot}sdk/installing/studio.html">Android Studio</a> for
|
||||
building your test apps, because it provides project setup, library inclusion, and packaging
|
||||
conveniences. This class assumes you are using Android Studio.</p>
|
||||
|
||||
<p>To automate UI tests with Android Studio, you implement your test code in a separate
|
||||
Android test folder ({@code src/androidTest/java}). The
|
||||
<a href="{@docRoot}tools/building/plugin-for-gradle.html">Android
|
||||
Plug-in for Gradle</a> builds a test app based on your test code, then loads the test app on the
|
||||
same device as the target app. In your test code, you can use UI testing frameworks to
|
||||
simulate user interactions on the target app, in order to perform testing tasks that cover specific
|
||||
usage scenarios.</p>
|
||||
|
||||
<p>For testing Android apps, you typically create these types of automated UI tests:</p>
|
||||
|
||||
<ul>
|
||||
<li><em>UI tests that span a single app:</em> This type of test verifies that the target app behaves
|
||||
as expected when a user performs a specific action or enters a specific input in its activities.
|
||||
It allows you to check that the target app returns the correct UI output in response
|
||||
to user interactions in the app’s activities. UI testing frameworks like Espresso allow you to
|
||||
programmatically simulate user actions and test complex intra-app user interactions.</li>
|
||||
<li><em>UI tests that span multiple apps:</em> This type of test verifies the correct behavior of
|
||||
interactions between different user apps or between user apps and system apps. For example, you
|
||||
might want to test that your camera app shares images correctly with a 3rd-party social media app,
|
||||
or with the default Android Photos app. UI testing frameworks that support cross-app interactions,
|
||||
such as UI Automator, allow you to create tests for such scenarios.</li>
|
||||
</ul>
|
||||
|
||||
<p>The lessons in this class teach you how to use the tools and APIs in the
|
||||
<a href="{@docRoot}/tools/testing-support-library/index.html">Android Testing Support Library</a>
|
||||
to build these types of automated tests. Before you begin building tests using these
|
||||
APIs, you must install the Android Testing Support Library, as described in
|
||||
<a href="{@docRoot}/tools/testing-support-library/index.html#setup">Downloading the Android
|
||||
Testing Support Library</a>.</p>
|
||||
|
||||
<h2>Lessons</h2>
|
||||
<dl>
|
||||
<dt><strong><a href="espresso-testing.html">
|
||||
Testing UI for a Single App</a></strong></dt>
|
||||
<dd>Learn how to test UI in a single app by using the Espresso testing framework.</dd>
|
||||
<dt><strong><a href="uiautomator-testing.html">
|
||||
Testing UI for Multiple Apps</a></strong></dt>
|
||||
<dd>Learn how to test UI in multiple apps by using the UI Automator testing framework</dd>
|
||||
</dl>
|
||||
520
docs/html/training/testing/ui-testing/uiautomator-testing.jd
Normal file
520
docs/html/training/testing/ui-testing/uiautomator-testing.jd
Normal file
@@ -0,0 +1,520 @@
|
||||
page.title=Testing UI for Multiple Apps
|
||||
page.tags=testing,ui automator
|
||||
trainingnavtop=true
|
||||
|
||||
@jd:body
|
||||
|
||||
<!-- This is the training bar -->
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dependencies and Prerequisites</h2>
|
||||
|
||||
<ul>
|
||||
<li>Android 4.3 (API level 18) or higher</li>
|
||||
<li><a href="{@docRoot}tools/testing-support-library/index.html">
|
||||
Android Testing Support Library</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>This lesson teaches you to</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="#setup">Set Up UI Automator</a></li>
|
||||
<li><a href="#build">Create a UI Automator Test Class</a></li>
|
||||
<li><a href="#run">Run UI Automator Tests on a Device or Emulator</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>You should also read</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="{@docRoot}reference/android/support/test/package-summary.html">
|
||||
UI Automator API Reference</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Try it out</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/googlesamples/android-testing"
|
||||
class="external-link">UI Automator Code Samples</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>A user interface (UI) test that involves user interactions across multiple apps lets you
|
||||
verify that your app behaves correctly when the user flow crosses into other apps or into the
|
||||
system UI. An example of such a user flow is a messaging app that lets the user enter a text
|
||||
message, launches the Android contact picker so that the users can select recipients to send the
|
||||
message to, and then returns control to the original app for the user to submit the message.</p>
|
||||
|
||||
<p>This lesson covers how to write such UI tests using the
|
||||
UI Automator testing framework provided by the
|
||||
<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
|
||||
The UI Automator APIs let you interact with visible elements on a device, regardless of
|
||||
which {@link android.app.Activity} is in focus. Your test can look up a UI component by using
|
||||
convenient descriptors such as the text displayed in that component or its content description. UI
|
||||
Automator tests can run on devices running Android 4.3 (API level 18) or higher.</p>
|
||||
|
||||
<p>The UI Automator testing framework is an instrumentation-based API and works
|
||||
with the
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
|
||||
{@code AndroidJUnitRunner}</a>
|
||||
test runner.
|
||||
</p>
|
||||
|
||||
<h2 id="setup">Set Up UI Automator</h2>
|
||||
<p>Before you begin using UI Automator, you must:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Install the Android Testing Support Library</strong>. The UI Automator API is
|
||||
located under the {@code com.android.support.test.uiautomator} package. These classes allow
|
||||
you to create tests that use the Espresso testing framework. To learn how to install the
|
||||
library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup">
|
||||
Testing Support Library Setup</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Set up your project structure.</strong> In your Gradle project, the source code for
|
||||
the target app that you want to test is typically placed under the {@code app/src/main}
|
||||
folder. The source code for instrumentation tests, including
|
||||
your UI Automator tests, must be placed under the <code>app/src/androidTest</code> folder.
|
||||
To learn more about setting up your project directory, see
|
||||
<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Specify your Android testing dependencies</strong>. In order for the
|
||||
<a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to
|
||||
correctly build and run your UI Automator tests, you must specify the following libraries in
|
||||
the {@code build.gradle} file of your Android app module:
|
||||
|
||||
<pre>
|
||||
dependencies {
|
||||
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
|
||||
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0'
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>To optimize your UI Automator testing, you should first inspect the target app’s UI components
|
||||
and ensure that they are accessible. These optimization tips are described in the next two
|
||||
sections.</p>
|
||||
|
||||
<h3 id="inspecting-ui">Inspecting the UI on a device</h3>
|
||||
<p>Before designing your test, inspect the UI components that are visible on the device. To
|
||||
ensure that your UI Automator tests can access these components, check that these components
|
||||
have visible text labels,
|
||||
<a href="http://developer.android.com/reference/android/view/View.html#attr_android:contentDescription">
|
||||
{@code android:contentDescription}</a>
|
||||
values, or both.</p>
|
||||
|
||||
<p>The {@code uiautomatorviewer} tool provides a convenient visual interface to inspect the layout
|
||||
hierarchy and view the properties of UI components that are visible on the foreground of the device.
|
||||
This information lets you create more fine-grained tests using UI Automator. For example, you can
|
||||
create a UI selector that matches a specific visible property. </p>
|
||||
|
||||
<p>To launch the {@code uiautomatorviewer} tool:</p>
|
||||
|
||||
<ol>
|
||||
<li>Launch the target app on a physical device.</li>
|
||||
<li>Connect the device to your development machine.</li>
|
||||
<li>Open a terminal window and navigate to the {@code <android-sdk>/tools/} directory.</li>
|
||||
<li>Run the tool with this command:
|
||||
<pre>$ uiautomatorviewer</pre>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>To view the UI properties for your application:</p>
|
||||
|
||||
<ol>
|
||||
<li>In the {@code uiautomatorviewer} interface, click the <strong>Device Screenshot</strong>
|
||||
button.</li>
|
||||
<li>Hover over the snapshot in the left-hand panel to see the UI components identified by the
|
||||
{@code uiautomatorviewertool}. The properties are listed in the lower right-hand panel and the
|
||||
layout hierarchy in the upper right-hand panel.</li>
|
||||
<li>Optionally, click on the <strong>Toggle NAF Nodes</strong> button to see UI components that
|
||||
are non-accessible to UI Automator. Only limited information may be available for these
|
||||
components.</li>
|
||||
</ol>
|
||||
|
||||
<p>To learn about the common types of UI components provided by Android, see
|
||||
<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>.</p>
|
||||
|
||||
<h3>Ensuring your Activity is accessible</h3>
|
||||
<p>The UI Automator test framework depends on the accessibility features of the Android framework
|
||||
to look up individual UI elements. As a developer, you should implement these minimum
|
||||
optimizations in your {@link android.app.Activity} to support UI Automator:</p>
|
||||
|
||||
<ul>
|
||||
<li>Use the
|
||||
<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
|
||||
{@code android:contentDescription}</a>
|
||||
attribute to label the {@link android.widget.ImageButton}, {@link android.widget.ImageView},
|
||||
{@link android.widget.CheckBox} and other user interface controls.</li>
|
||||
<li>Provide an <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a>
|
||||
attribute instead of a content description for {@link android.widget.EditText} fields.</li>
|
||||
<li>Associate an <a href="http://developer.android.com/reference/android/widget/TextView.html#attr_android:hint">
|
||||
{@code android:hint}</a>
|
||||
attribute with any graphical icons used by controls that provide feedback to the user
|
||||
(for example, status or state information).</li>
|
||||
<li>Use the {@code uiautomatorviewer} tool to ensure that the UI component is accessible to the
|
||||
testing framework. You can also test the application by turning on accessibility services like
|
||||
TalkBack and Explore by Touch, and try using your application using only directional controls.</li>
|
||||
</ul>
|
||||
|
||||
<p>Generally, app developers get accessibility support for free, courtesy of
|
||||
the {@link android.view.View} and {@link android.view.ViewGroup}
|
||||
classes. However, some apps use custom view elements to provide a richer user experience. Such
|
||||
custom elements won't get the accessibility support that is provided by the standard Android UI
|
||||
elements. If this applies to your app, make sure that it exposes the custom-drawn UI element to
|
||||
Android accessibility services by implementing the
|
||||
{@link android.view.accessibility.AccessibilityNodeProvider} class.</p>
|
||||
|
||||
<p>If the custom view element contains a single element, make it accessible by
|
||||
<a href="{@docRoot}guide/topics/ui/accessibility/apps.html#accessibility-methods">implementing
|
||||
accessibility API methods</a>.
|
||||
If the custom view contains elements that are not views themselves (for example, a
|
||||
{@link android.webkit.WebView}, make sure it implements the
|
||||
{@link android.view.accessibility.AccessibilityNodeProvider} class. For container views that
|
||||
extend an existing container implementation
|
||||
(for example, a {@link android.widget.ListView}), implementing
|
||||
{@link android.view.accessibility.AccessibilityNodeProvider} is not necessary.</p>
|
||||
|
||||
<p>For more information about implementing and testing accessibility, see
|
||||
<a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>.</p>
|
||||
|
||||
<h2 id="build">Create a UI Automator Test Class</h2>
|
||||
|
||||
<p>To build a UI Automator test, create a class that extends
|
||||
{@link android.test.InstrumentationTestCase}. Implement the following programming model in your
|
||||
UI Automator test class:</p>
|
||||
|
||||
<ol>
|
||||
<li>Get a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
|
||||
object to access the device you want to test, by calling the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#getInstance(android.app.Instrumentation)">
|
||||
{@code getInstance()}</a>
|
||||
method and passing it an {@link android.app.Instrumentation} object as the argument.</li>
|
||||
<li>Get a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
object to access a UI component that is displayed on the device
|
||||
(for example, the current view in the foreground), by calling the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)">
|
||||
{@code findObject()}</a>
|
||||
method.
|
||||
</li>
|
||||
<li>Simulate a specific user interaction to perform on that UI component, by calling a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
method; for example, call
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#performMultiPointerGesture(android.view.MotionEvent.PointerCoords[]...)">
|
||||
{@code performMultiPointerGesture()}</a>
|
||||
to simulate a multi-touch gesture, and
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)">{@code setText()}</a>
|
||||
to edit a text field. You can call on the APIs in steps 2 and 3 repeatedly as necessary to test
|
||||
more complex user interactions that involve multiple UI components or sequences of user actions.</li>
|
||||
<li>Check that the UI reflects the expected state or behavior, after these user interactions are
|
||||
performed. </li>
|
||||
</ol>
|
||||
|
||||
<p>These steps are covered in more detail in the sections below.</p>
|
||||
|
||||
<h3 id="accessing-ui-components">Accessing UI Components</h3>
|
||||
<p>The
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
|
||||
object is the primary way you access and manipulate the state of the
|
||||
device. In your tests, you can call
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
|
||||
methods to check for the state of various properties, such as current orientation or display size.
|
||||
Your test can use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
|
||||
object to perform device-level actions, such as forcing the device into a specific rotation,
|
||||
pressing D-pad hardware buttons, and pressing the Home and Menu buttons.</p>
|
||||
|
||||
<p>It’s good practice to start your test from the Home screen of the device. From the Home screen
|
||||
(or some other starting location you’ve chosen in the device), you can call the methods provided by
|
||||
the UI Automator API to select and interact with specific UI elements. </p>
|
||||
|
||||
<p>The following code snippet shows how your test might get an instance of
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
|
||||
and simulate a Home button press:</p>
|
||||
|
||||
<pre>
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.support.test.uiautomator.By;
|
||||
|
||||
public class CalculatorUiTest extends InstrumentationTestCase {
|
||||
|
||||
private UiDevice mDevice;
|
||||
|
||||
public void setUp() {
|
||||
// Initialize UiDevice instance
|
||||
mDevice = UiDevice.getInstance(getInstrumentation());
|
||||
|
||||
// Start from the home screen
|
||||
mDevice.pressHome();
|
||||
mDevice.wait(Until.hasObject(By.pkg(getHomeScreenPackage()).depth(0)),
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)">{@code findObject()}</a>
|
||||
method to retrieve a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
which represents a view that matches a given selector criteria. You can reuse the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
instances that you have created in other parts of your app testing, as needed. Note that the
|
||||
UI Automator test framework searches the current display for a match every time your test uses a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
instance to click on a UI element or query a property.</p>
|
||||
|
||||
<p>The following snippet shows how your test might construct
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
instances that represent a Cancel button and a OK button in an app.</p>
|
||||
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4 id="specifying-selector">Specifying a selector</h4>
|
||||
<p>If you want to access a specific UI component in an app, use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
|
||||
class. This class represents a query for specific elements in the
|
||||
currently displayed UI. </p>
|
||||
|
||||
<p>If more than one matching element is found, the first matching element in the layout hierarchy
|
||||
is returned as the target
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>.
|
||||
When constructing a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>,
|
||||
you can chain together multiple properties to refine your search. If no matching UI element is
|
||||
found, a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObjectNotFoundException.html">
|
||||
{@code UiAutomatorObjectNotFoundException}</a> is thrown. </p>
|
||||
|
||||
<p>You can use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html#childSelector(android.support.test.uiautomator.UiSelector)">{@code childSelector()}</a>
|
||||
method to nest multiple
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
|
||||
instances. For example, the following code example shows how your test might specify a search to
|
||||
find the first {@link android.widget.ListView} in the currently displayed UI, then search within that
|
||||
{@link android.widget.ListView} to find a UI element with the text property Apps.</p>
|
||||
|
||||
<pre>
|
||||
UiObject appItem = new UiObject(new UiSelector()
|
||||
.className("android.widget.ListView")
|
||||
.instance(1)
|
||||
.childSelector(new UiSelector()
|
||||
.text("Apps")));
|
||||
</pre>
|
||||
|
||||
<p>As a best practice, when specifying a selector, you should use a Resource ID (if one is assigned
|
||||
to a UI element) instead of a text element or content-descriptor. Not all elements have a text
|
||||
element (for example, icons in a toolbar). Text selectors are brittle and can lead to test failures
|
||||
if there are minor changes to the UI. They may also not scale across different languages; your text
|
||||
selectors may not match translated strings.</p>
|
||||
|
||||
<p>It can be useful to specify the object state in your selector criteria. For example, if you want
|
||||
to select a list of all checked elements so that you can uncheck them, call the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/By.html#checked(boolean)">
|
||||
{@code checked()}</a>
|
||||
method with the argument set to {@code true}.</p>
|
||||
|
||||
<h3 id="performing-actions">Performing Actions</h3>
|
||||
|
||||
<p>Once your test has obtained a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
object, you can call the methods in the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
|
||||
class to perform user interactions on the UI component represented by that
|
||||
object. You can specify such actions as:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#click()">
|
||||
{@code click()}</a>
|
||||
: Clicks the center of the visible bounds of the UI element.</li>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#dragTo(int, int, int)">
|
||||
{@code dragTo()}</a>
|
||||
: Drags this object to arbitrary coordinates.</li>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)">
|
||||
{@code setText()}</a>
|
||||
: Sets the text in an editable field, after clearing the field's content.
|
||||
Conversely, the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#clearTextField()">
|
||||
{@code clearTextField()}</a>
|
||||
method clears the existing text in an editable field.</li>
|
||||
<li>
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeUp(int)">
|
||||
{@code swipeUp()}</a>
|
||||
: Performs the swipe up action on the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>.
|
||||
Similarly, the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeDown(int)">
|
||||
{@code swipeDown()}</a>,
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeLeft(int)">
|
||||
{@code swipeLeft()}</a>, and
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeRight(int)">
|
||||
{@code swipeRight()}</a>
|
||||
methods perform corresponding actions.</li>
|
||||
</ul>
|
||||
|
||||
<p>The UI Automator testing framework allows you to send an
|
||||
{@link android.content.Intent}
|
||||
or launch an {@link android.app.Activity}
|
||||
without using shell commands, by getting a
|
||||
{@link android.content.Context}
|
||||
object through
|
||||
{@link android.app.Instrumentation#getContext() getContext()}.</p>
|
||||
|
||||
<p>The following snippet shows how your test can use an
|
||||
{@link android.content.Intent} to launch the app under test. This approach is useful when you are
|
||||
only interested in testing the calculator app, and don't care about the launcher.</p>
|
||||
|
||||
<pre>
|
||||
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);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4 id="actions-on-collections">Performing actions on collections</h4>
|
||||
|
||||
<p>Use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
|
||||
{@code UiCollection}</a>
|
||||
class if you want to simulate user interactions on a
|
||||
collection of items (for example, songs in a music album or a list of emails in an Inbox). To
|
||||
create a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
|
||||
{@code UiCollection}</a>
|
||||
object, specify a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
|
||||
that searches for a
|
||||
UI container or a wrapper of other child UI elements, such as a layout view that contains child UI
|
||||
elements.</p>
|
||||
|
||||
<p>The following code snippet shows how your test might construct a
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
|
||||
{@code UiCollection}</a>
|
||||
to represent a video album that is displayed within a {@link android.widget.FrameLayout}:</p>
|
||||
|
||||
<pre>
|
||||
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 it
|
||||
UiObject video = videos.getChildByText(new UiSelector()
|
||||
.className("android.widget.LinearLayout"), "Cute Baby Laughing");
|
||||
video.click();
|
||||
|
||||
// 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();
|
||||
</pre>
|
||||
|
||||
<h4 id="actions-on-scrollable-views">Performing actions on scrollable views</h4>
|
||||
<p>Use the
|
||||
<a href="{@docRoot}reference/android/support/test/uiautomator/UiScrollable.html">
|
||||
{@code UiScrollable}</a>
|
||||
class to simulate vertical or horizontal scrolling across a display. This technique is helpful when
|
||||
a UI element is positioned off-screen and you need to scroll to bring it into view.</p>
|
||||
|
||||
<p>The following code snippet shows how to simulate scrolling down the Settings menu and clicking
|
||||
on an About tablet option:</p>
|
||||
|
||||
<pre>
|
||||
UiScrollable settingsItem = new UiScrollable(new UiSelector()
|
||||
.className("android.widget.ListView"));
|
||||
UiObject about = settingsItem.getChildByText(new UiSelector()
|
||||
.className("android.widget.LinearLayout"), "About tablet");
|
||||
about.click();
|
||||
</pre>
|
||||
|
||||
<h3 id="verifying-results">Verifying Results</h3>
|
||||
<p>The {@link android.test.InstrumentationTestCase} extends {@link junit.framework.TestCase}, so
|
||||
you can use standard JUnit <a href="http://junit.org/javadoc/latest/org/junit/Assert.html"
|
||||
class="external-link">{@code Assert}</a> methods to test
|
||||
that UI components in the app return the expected results. </p>
|
||||
|
||||
<p>The following snippet shows how your test can locate several buttons in a calculator app, click
|
||||
on them in order, then verify that the correct result is displayed.</p>
|
||||
|
||||
<pre>
|
||||
private static final String CALC_PACKAGE = "com.myexample.calc";
|
||||
|
||||
public void testTwoPlusThreeEqualsFive() {
|
||||
// Enter an equation: 2 + 3 = ?
|
||||
mDevice.findObject(new UiSelector()
|
||||
.packageName(CALC_PACKAGE).resourceId("two")).click();
|
||||
mDevice.findObject(new UiSelector()
|
||||
.packageName(CALC_PACKAGE).resourceId("plus")).click();
|
||||
mDevice.findObject(new UiSelector()
|
||||
.packageName(CALC_PACKAGE).resourceId("three")).click();
|
||||
mDevice.findObject(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());
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2 id="run">Run UI Automator Tests on a Device or Emulator</h2>
|
||||
<p>UI Automator tests are based on the {@link android.app.Instrumentation} class. The
|
||||
<a href="https://developer.android.com/tools/building/plugin-for-gradle.html">
|
||||
Android Plug-in for Gradle</a>
|
||||
provides a default directory ({@code src/androidTest/java}) for you to store the instrumented test
|
||||
classes and test suites that you want to run on a device. The plug-in compiles the test
|
||||
code in that directory and then executes the test app using a test runner class. You are
|
||||
strongly encouraged to use the
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
|
||||
class provided in the
|
||||
<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>
|
||||
as your default test runner. </p>
|
||||
|
||||
<p>To run UI Automator tests in your Gradle project:</p>
|
||||
|
||||
<ol>
|
||||
<li>Specify
|
||||
<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
|
||||
as the default test instrumentation runner in your {@code build.gradle} file:
|
||||
<pre>
|
||||
android {
|
||||
defaultConfig {
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
}</pre>
|
||||
</li>
|
||||
<li>Run your tests from the command-line by calling the {@code connectedCheck}
|
||||
(or {@code cC}) task:
|
||||
<pre>./gradlew cC</pre>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -1840,6 +1840,24 @@ results."
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li class="nav-section">
|
||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/testing/ui-testing/index.html"
|
||||
description="How to automate your user interface tests for Android apps.">
|
||||
Automating UI Tests
|
||||
</a></div>
|
||||
<ul>
|
||||
<li><a href="<?cs var:toroot ?>training/testing/ui-testing/espresso-testing.html">
|
||||
<span class="en">Testing UI for a Single App</span>
|
||||
</a>
|
||||
</li>
|
||||
<li><a href="<?cs var:toroot ?>training/testing/ui-testing/uiautomator-testing.html">
|
||||
<span class="en">Testing UI for Multiple Apps</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- End best Testing -->
|
||||
|
||||
|
||||
Reference in New Issue
Block a user