Merge "docs: Added new docs for uiautomator testing framework." into jb-mr1-dev

This commit is contained in:
Quddus Chong
2012-11-12 15:02:33 -08:00
committed by Android (Google) Code Review
14 changed files with 14872 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View File

@@ -280,7 +280,7 @@ and may be out of date. For the most current list of options, execute <code>andr
</tr>
<tr>
<td rowspan="3"><code>create-test-project</code></td>
<td rowspan="3"><code>create test-project</code></td>
<td><code>-n &lt;name&gt;</code></td>
@@ -306,7 +306,7 @@ and may be out of date. For the most current list of options, execute <code>andr
</tr>
<tr>
<td rowspan="2"><code>update-test-project</code></td>
<td rowspan="2"><code>update test-project</code></td>
<td><code>-p &lt;path&gt;</code></td>
@@ -324,7 +324,7 @@ and may be out of date. For the most current list of options, execute <code>andr
</tr>
<tr>
<td rowspan="4"><code>create-lib-project</code></td>
<td rowspan="4"><code>create lib-project</code></td>
<td><code>-k &lt;packageName&gt;</code></td>
@@ -358,7 +358,7 @@ and may be out of date. For the most current list of options, execute <code>andr
</tr>
<tr>
<td rowspan="3"><code>update-lib-project</code></td>
<td rowspan="3"><code>update lib-project</code></td>
<td><code>-p &lt;path&gt;</code></td>
@@ -382,6 +382,30 @@ and may be out of date. For the most current list of options, execute <code>andr
<td></td>
</tr>
<tr>
<td rowspan="3"><code>create uitest-project</code></td>
<td><code>-n &lt;name&gt;</code></td>
<td>The name of the UI test project</td>
<td></td>
</tr>
<tr>
<td><code>-t &lt;name&gt;</code></td>
<td>Target ID of the UI test project</td>
<td>Required</td>
</tr>
<tr>
<td><code>-p &lt;path&gt;</code></td>
<td>Location path of the UI test project</td>
<td>Required</td>
</tr>
</table>
<h3>Update actions</h3>

View File

@@ -0,0 +1,168 @@
page.title=IAutomationSupport
parent.title=uiautomator
parent.link=index.html
@jd:body
<style>
h4.jd-details-title {background-color: #DEE8F1;}
</style>
<h2>Class Overview</h2>
<p>Provides auxiliary support for running test cases
</p>
</div><!-- jd-descr -->
<div class="jd-descr">
<h2>Summary</h2>
<!-- ========== METHOD SUMMARY =========== -->
<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
<tr class="api" >
<td class="jd-typecol">
abstract
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad"><a href="#sendStatus(int, android.os.Bundle)">sendStatus</a></span>(int resultCode, Bundle status)
<div class="jd-descrdiv">Allows the running test cases to send out interim status</div>
</td></tr>
</table>
</div><!-- jd-descr (summary) -->
<!-- Details -->
<!-- XML Attributes -->
<!-- Enum Values -->
<!-- Constants -->
<!-- Fields -->
<!-- Public ctors -->
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<!-- Protected ctors -->
<!-- ========= METHOD DETAIL ======== -->
<!-- Public methdos -->
<h2>Public Methods</h2>
<a id="sendStatus(int, android.os.Bundle)"></a>
<div class="jd-details api ">
<h4 class="jd-details-title">
<span class="normal">
public
abstract
void
</span>
<span class="sympad">sendStatus</span>
<span class="normal">(int resultCode, Bundle status)</span>
</h4>
<div class="api-level">
<div>
</div>
</div>
<div class="jd-details-descr">
<div class="jd-tagdata jd-tagdescr"><p>Allows the running test cases to send out interim status</p></div>
</div>
</div>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,630 @@
page.title=UiObjectNotFoundException
parent.title=uiautomator
parent.link=index.html
@jd:body
<style>
h4.jd-details-title {background-color: #DEE8F1;}
</style>
<p>Generated in test runs when a <code><a href="UiSelector.html">UiSelector</a></code> selector could not be matched
to any UI element displayed.
</p>
<div class="jd-descr">
<h2>Summary</h2>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
<tr class="api" >
<td class="jd-typecol">
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad"><a href="#UiObjectNotFoundException(java.lang.String)">UiObjectNotFoundException</a></span>(String msg)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad"><a href="#UiObjectNotFoundException(java.lang.String, java.lang.Throwable)">UiObjectNotFoundException</a></span>(String detailMessage, Throwable throwable)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad"><a href="#UiObjectNotFoundException(java.lang.Throwable)">UiObjectNotFoundException</a></span>(Throwable throwable)
</td></tr>
</table>
<!-- ========== METHOD SUMMARY =========== -->
<table id="inhmethods" class="jd-sumtable"><tr><th>
<a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
<div style="clear:left;">Inherited Methods</div></th></tr>
<tr class="api apilevel-" >
<td colspan="12">
<a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Throwable" class="jd-expando-trigger closed"
><img id="inherited-methods-java.lang.Throwable-trigger"
src="../../../../../assets/images/triangle-closed.png"
class="jd-expando-trigger-img" /></a>
From class
java.lang.Throwable
<div id="inherited-methods-java.lang.Throwable">
<div id="inherited-methods-java.lang.Throwable-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-methods-java.lang.Throwable-summary" style="display: none;">
<table class="jd-sumtable-expando">
<tr class="api" >
<td class="jd-typecol">
synchronized
Throwable
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">fillInStackTrace</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
Throwable
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">getCause</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
String
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">getLocalizedMessage</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
String
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">getMessage</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
StackTraceElement[]
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">getStackTrace</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
synchronized
Throwable
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">initCause</span>(Throwable arg0)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">printStackTrace</span>(PrintWriter arg0)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">printStackTrace</span>(PrintStream arg0)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">printStackTrace</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">setStackTrace</span>(StackTraceElement[] arg0)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
String
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">toString</span>()
</td></tr>
</table>
</div>
</div>
</td></tr>
<tr class="api apilevel-" >
<td colspan="12">
<a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
><img id="inherited-methods-java.lang.Object-trigger"
src="../../../../../assets/images/triangle-closed.png"
class="jd-expando-trigger-img" /></a>
From class
java.lang.Object
<div id="inherited-methods-java.lang.Object">
<div id="inherited-methods-java.lang.Object-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-methods-java.lang.Object-summary" style="display: none;">
<table class="jd-sumtable-expando">
<tr class="api" >
<td class="jd-typecol">
boolean
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">equals</span>(Object arg0)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
Class&lt;?&gt;
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">getClass</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
int
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">hashCode</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">notify</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">notifyAll</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
String
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">toString</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">wait</span>()
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">wait</span>(long arg0, int arg1)
</td></tr>
<tr class="api" >
<td class="jd-typecol">
final
void
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad">wait</span>(long arg0)
</td></tr>
</table>
</div>
</div>
</td></tr>
</table>
</div><!-- jd-descr (summary) -->
<!-- Details -->
<!-- XML Attributes -->
<!-- Enum Values -->
<!-- Constants -->
<!-- Fields -->
<!-- Public ctors -->
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<h2>Public Constructors</h2>
<a id="UiObjectNotFoundException(java.lang.String)"></a>
<div class="jd-details api ">
<h4 class="jd-details-title">
<span class="normal">
public
</span>
<span class="sympad">UiObjectNotFoundException</span>
<span class="normal">(String msg)</span>
</h4>
<div class="api-level">
<div>
</div>
</div>
<div class="jd-details-descr">
<div class="jd-tagdata jd-tagdescr"><p></p></div>
</div>
</div>
<a id="UiObjectNotFoundException(java.lang.String, java.lang.Throwable)"></a>
<div class="jd-details api ">
<h4 class="jd-details-title">
<span class="normal">
public
</span>
<span class="sympad">UiObjectNotFoundException</span>
<span class="normal">(String detailMessage, Throwable throwable)</span>
</h4>
<div class="api-level">
<div>
</div>
</div>
<div class="jd-details-descr">
<div class="jd-tagdata jd-tagdescr"><p></p></div>
</div>
</div>
<a id="UiObjectNotFoundException(java.lang.Throwable)"></a>
<div class="jd-details api ">
<h4 class="jd-details-title">
<span class="normal">
public
</span>
<span class="sympad">UiObjectNotFoundException</span>
<span class="normal">(Throwable throwable)</span>
</h4>
<div class="api-level">
<div>
</div>
</div>
<div class="jd-details-descr">
<div class="jd-tagdata jd-tagdescr"><p></p></div>
</div>
</div>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
page.title=UiWatcher
parent.title=uiautomator
parent.link=index.html
@jd:body
<style>
h4.jd-details-title {background-color: #DEE8F1;}
</style>
<p>Represents a conditional watcher on the target device. To learn how to register a conditional
watcher, see <code><a href="UiDevice.html#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">UiDevice.registerWatcher()</a></code>.
</p>
<div class="jd-descr">
<h2>Summary</h2>
<!-- ========== METHOD SUMMARY =========== -->
<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
<tr class="api" >
<td class="jd-typecol">
abstract
boolean
</td>
<td class="jd-linkcol" width="100%">
<span class="sympad"><a href="#checkForCondition()">checkForCondition</a></span>()
<div class="jd-descrdiv">The testing framework calls this handler method automatically when the framework
is unable to find a match using the <code><a href="UiSelector.html">UiSelector</a></code>.</div>
</td></tr>
</table>
</div><!-- jd-descr (summary) -->
<!-- ========= METHOD DETAIL ======== -->
<!-- Public methdos -->
<h2>Public Methods</h2>
<a id="checkForCondition()"></a>
<div class="jd-details api ">
<h4 class="jd-details-title">
<span class="normal">
public
abstract
boolean
</span>
<span class="sympad">checkForCondition</span>
<span class="normal">()</span>
</h4>
<div class="api-level">
</div>
<div class="jd-details-descr">
<div class="jd-tagdata jd-tagdescr"><p>The testing framework calls this handler method automatically when the framework is unable to find a match using the <code><a href="UiSelector.html">UiSelector</a></code>. When a match is not found after a predetermined time has elapsed, the framework calls the checkForCondition() method of all registered watchers on the device. You can use this method to handle known blocking issues that are preventing the test from proceeding. For example, you can check if a dialog appeared that is blocking the the test, then close the dialog or perform some other appropriate action to allow the test to continue.</p></div>
<div class="jd-tagdata">
<h5 class="jd-tagtitle">Returns</h5>
<ul class="nolist"><li>true to indicate a matched condition, or false if no matching condition is found
</li></ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,177 @@
page.title=uiautomator
parent.title=Tools
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ul>
<li><a href="#syntax">Syntax</a></li>
<li><a href="#options">Options</a></li>
<lI><a href="#api">uiautomator API</a>
<ul>
<li><a href="#classes">Classes</a></li>
<li><a href="#interfaces">Interfaces</a></li>
<li><a href="#exceptions">Exceptions</a></li>
</ul>
</lI>
</ul>
</div>
</div>
<p>The {@code uiautomator} testing framework lets you test your user interface (UI) efficiently by creating automated functional UI testcases that can be run against your app on one or more devices.</p>
<p>For more information on testing with the {@code uiautomator} framework, see <a href="{@docRoot}tools/testing/testing_ui.html">UI Testing</a>.</p>
<h2 id="syntax">Syntax</h2>
<p>To run your testcases on the target device, you can use the {@code adb shell} command to invoke the {@code uiautomator} tool. The syntax is:
<pre>
adb shell uiautomator runtest &lt;jar&gt; -c &lt;test_class_or_method&gt; [options]
</pre>
</p>
<p>Heres an example:</p>
<pre>adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings</pre>
<h2 id="options">Command-line Options</h2>
<p>The following table describes the subcommands and options for {@code uiautomator}.</p>
<p class="table-caption" id="table1">
<strong>Table 1.</strong> Command-line options for {@code uiautomator}</p>
<table>
<tr>
<th>Subcommand</th>
<th>Option</th>
<th>Description</th>
</tr>
<tr>
<td rowspan="6"><code>runtest</code></td>
<td><nobr>{@code &lt;jar&gt;}</nobr></td>
<td><strong>Required</strong>. The {@code &lt;jar&gt;} argument is the name of one or more JAR files that you deployed to the target device which contain your uiautomator testcases. You can list more than one JAR file by using a space as a separator.</td>
</tr>
<tr>
<td><nobr><code>-c &lt;test_class_or_method&gt; </code></nobr></td>
<td><strong>Required</strong>. The {@code &lt;test_class_or_method&gt;} argument is a list of one or more specific test classes or test methods from the JARs that you want {@code uiautomator} to run. <p>Each class or method must be fully qualified with the package name, in one of these formats:
<ul>
<li>{@code package_name.class_name}</li>
<li>{@code package_name.class_name#method_name}</li>
</ul>
You can list multiple classes or methods by using a space as a separator.</p></td>
</tr>
<tr>
<td><nobr><code>--nohup</code></nobr></td>
<td>Runs the test to completion on the device even if its parent process is terminated (for example, if the device is disconnected).</td>
</tr>
<tr>
<td><nobr><code>-e &lt;NAME&gt; &lt;VALUE&gt;</code></nobr></td>
<td><p>Specify other name-value pairs to be passed to test classes. May be repeated.</p><p class="note"><strong>Note: </strong>The {@code -e} options cannot be combined; you must prefix each option with a separate {@code -e} flag. </p></td>
</tr>
<tr>
<td><nobr><code>-e debug [true|false]</code></nobr></td>
<td>Wait for debugger to connect before starting.</td>
</tr>
<tr>
<td><nobr><code>-e runner [CLASS]</code></nobr></td>
<td>Use the specified test runner class instead. If unspecified, the {@code uiautomator} frameworks default runner will be used.</td>
</tr>
<tr>
<td><code>dump</code></td>
<td><code>[file]</code></td>
<td>Generate an XML file with a dump of the current UI hierarchy. If a filepath is not specified, by default, the generated dump file is stored on the device in this location {@code /storage/sdcard0/window_dump.xml}.</td>
</tr>
<tr>
<td><code>events</code></td>
<td>&nbsp;</td>
<td>Prints out accessibility events to the console until the connection to the device is terminated</td>
</tr>
</table>
<h2 id="api">uiautomator API</h2>
<p>The {@code uiautomator} API is bundled in the {@code uiautomator.jar} file under the {@code &lt;android-sdk&gt;/platforms/} directory. The API includes these key classes, interfaces, and exceptions that allow you to capture and manipulate UI components on the target app:</p>
<h3 id="classes">Classes</h3>
<table>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code com.android.uiautomator.core.UiCollection}</a></nobr></td>
<td>Used to enumerate a container's user interface (UI) elements for the purpose of counting, or targeting a sub elements by a child's text or description.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code com.android.uiautomator.core.UiDevice}</a></nobr></td>
<td>Provides access to state information about the device. You can also use this class to simulate user actions on the device, such as pressing the d-pad hardware button or pressing the Home and Menu buttons.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code com.android.uiautomator.core.UiObject}</a></nobr></td>
<td>Represents a user interface (UI) element.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">{@code com.android.uiautomator.core.UiScrollable}</a></nobr></td>
<td>Provides support for searching for items in a scrollable UI container.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code com.android.uiautomator.core.UiSelector}</a></nobr></td>
<td>Represents a query for one or more target UI elements on a device screen. </td>
</tr>
</table>
<h3 id="interfaces">Interfaces</h3>
<table>
<tr>
<th>Interface</th>
<th>Description</th>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiWatcher.html">{@code com.android.uiautomator.core.UiWatcher}</a></nobr></td>
<td>Represents a conditional watcher on the target device.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/IAutomationSupport.html">{@code com.android.uiautomator.testrunner.IAutomationSupport}</a></nobr></td>
<td>Provides auxiliary support for running test cases.</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code com.android.uiautomator.testrunner.UiAutomatorTestCase}</a></nobr></td>
<td>Defines an environment for running multiple tests. All {@code uiautomator} test cases should extend this class.</td>
</tr>
</table>
<h3 id="exceptions">Exceptions</h3>
<table>
<tr>
<th>Exception</th>
<th>Description</th>
</tr>
<tr>
<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiObjectNotFoundException.html">{@code com.android.uiautomator.core.UiObjectNotFoundException}</a></nobr></td>
<td>Indicates when a a <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> could not be matched to any UI element displayed.</td>
</tr>
</table>

View File

@@ -0,0 +1,356 @@
page.title=UI Testing
parent.title=Testing
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#overview">Overview</a></li>
<ul>
<li><a href="#workflow">Workflow</a></li>
</ul>
<li><a href="#uianalysis">Analyzing Your UI</a></li>
<li><a href="#prepare">Preparing to Test</a>
<ul>
<LI><a href="#loading">Load the App</a></LI>
<LI><a href="#identifyUI">Identify UI Components</a></LI>
<LI><a href="#accessibility">Ensure Accessibility</a></LI>
<LI><a href="#configure">Configure Development Environment</a></LI>
</ul>
</li>
<li><a href="#creating">Creating Tests</a>
<ul>
<LI><a href="#classes">uiautomator API</a></LI>
<li><a href="#sample">Sample Test Case</a>
</ul>
</li>
<li><a href="#builddeploy">Building and Deploying Tests</a></li>
<li><a href="#running">Running Tests</a></li>
<li><a href="#bestpractices">Best Practices</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li><a href="{@docRoot}tools/help/uiautomator/IAutomationSupport.html">IAutomationSupport</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">UiAutomatorTestCase</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">UiCollection</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">UiDevice</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiObject.html">UiObject</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">UiScrollable</a></li>
<li><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">UiSelector</a></li>
</ol>
<h2>See Also</h2>
<ol>
<li>
<a href="{@docRoot}tools/help/uiautomator/index.html">uiautomator (reference)</a>
</li>
</ol>
</div>
</div>
<p>
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 applications 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.
</p>
<p>
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.
</p>
<p>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.</p>
<h2 id="overview">Overview</h2>
<p>The Android SDK provides the following tools to support automated, functional UI testing on your application:
<ul>
<LI>{@code uiautomatorviewer} - A GUI tool to scan and analyze the UI components of an Android application.</LI>
<LI>{@code uiautomator} - A Java library containing APIs to create customized functional UI tests, and an execution engine to automate and run the tests.</LI>
</ul></p>
<p>To use these tools, you must have the following versions of the Android development tools installed:
<ul>
<LI>Android SDK Tools, Revision 21 or higher</LI>
<LI>Android SDK Platform, API 16 or higher</LI>
</ul>
</p>
<h3 id="workflow">Workflow for the the uiautomator testing framework</h3>
<p>Here's a short overview of the steps required to automate UI testing:
<ol>
<LI>Prepare to test by installing the app on a test device, analyzing the apps UI components, and ensuring that your application is accessible by the test automation framework.</LI>
<li>Create automated tests to simulate specific user interactions on your application.</li>
<li>Compile your test cases into a JAR file and install it on your test device along with your app.</li>
<li>Run the tests and view the test results.</li>
<li>Correct any bugs or defects discovered in testing.</li>
</ol>
</p>
<h2 id="uianalysis">Analyzing Your Application's UI</h2>
<p>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.</p>
<a href="{@docRoot}images/testing/UIAutomatorViewer.png">
<img src="{@docRoot}images/testing/UIAutomatorViewer.png"
alt="User interface of uiautomatorviewer tool" height="327px" id="figure1"/>
</a>
<p class="img-caption">
<strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test deviice.
</p>
<p>To analyze the UI components of the application that you want to test:</p>
<ol>
<li>Connect your Android device to your development machine.</li>
<li>Open a terminal window and navigate to {@code &lt;android-sdk&gt;/tools/}.</li>
<LI>Run the tool with this command:<pre>$ uiautomatorviewer</pre></LI>
<li><p>To capture a screen for analysis, click the <strong>Device Screenshot</strong> button in the GUI of the {@code uiautomatorviewer} tool.</p>
<p class="note"><strong>Note: </strong>If you have more than one device connected, specify the device for screen capture by setting the {@code ANDROID_SERIAL} environment variable:
<ol type="a">
<li>Find the serial numbers for your connected devices by running this command:<pre>$ adb devices</pre> </li>
<li>Set the {@code ANDROID_SERIAL} environment variable to select the device to test:
<ul>
<li>In Windows: <pre>set ANDROID_SERIAL=&lt;device serial number&gt;</pre></li>
<li>In UNIX: <pre>export ANDROID_SERIAL=&lt;device serial number&gt;</pre></li>
</ul>
</li>
</ol>
If you are connected to only a single device, you do not need to set the ANDROID_SERIAL environment variable.</p>
</li>
<li>View the UI properties for your application:
<ul>
<LI>Hover over the snapshot in the left-hand panel to see the UI components identified by the {@code uiautomatorviewer} tool. You can view the components properties 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 not accessible to the {@code uiautomator} testing framework. Only limited information may be available for these components.</li>
</ul>
</li>
</ol>
<h2 id="prepare">Preparing to Test</h2>
<p>Before using the {@code uiautomator} testing framework, complete these pre-flight tasks:
</p>
<h3 id="loading">Load the application to a device</h3>
<p>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 <a href="@docRoot}/tools/help/adb.html#move">{@code adb}</a> documentation. </p>
<h3 id="identifyUI">Identify the applications UI components</h3>
<p>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, <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code android:contentDescription}</a> values, or both.
<p>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 <a href="#uianalaysis">Analyzing Your Applications UI</a>. For more information about the common types of UI components provided by Android, see <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>.</p>
<h3 id="accessibility">Ensure that the application is accessible</h3>
<p>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:
<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 {@code <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>} attribute <em>instead</em> of a content description for {@link android.widget.EditText} fields</li>
<li>Associate an <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">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>Make sure that all the user interface elements are accessible with a directional controller, such as a trackball or D-pad.</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>
<p>For more information about implementing and testing accessibility, see <a href="{@docRoot}/guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>.</p>
<p class="note"><strong>Note: </strong>To identify the non-accessible components in the UI, click on the <strong>Toggle NAF Nodes</strong> option in the {@code uiautomatorviewer} tool.</p>
<p>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 <a href="{@docRoot}/guide/topics/ui/accessibility/apps.html#custom-views">Making Applications Accessible</a>.</p>
<h3 id="configure">Configure your development environment</h3>
<p>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:</p>
<ol>
<li>Create a new Java project in Eclipse, and give your project a name that is relevant to the tests youre about to create (for example, "MyAppNameTests"). In the project, you will create the test cases that are specific to the application that you want to test.</li>
<li>From the <strong>Project Explorer</strong>, right-click on the new project that you created, then select <strong>Properties > Java Build Path</strong>, and do the following:
<ol type="a">
<LI>Click <strong>Add Library > JUnit</strong> then select <strong>JUnit3</strong> to add JUnit support.</LI>
<li>Click <strong>Add External JARs...</strong> and navigate to the SDK directory. Under the platforms directory, select the latest SDK version and add both the {@code uiautomator.jar} and {@code android.jar} files.</li>
</ol>
</li>
</ol>
<p>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 &lt;android-sdk&gt;/platforms/&lt;sdk&gt;} directory are in your Java class path.</p>
<p>Once you have completed these prerequisite tasks, you're almost ready to start creating your {@code uiautomator} tests. </li>
<h2 id="creating">Creating uiautomator Tests</h2>
<p>To build a test that runs in the {@code uiautomator} framework, create a test case that extends the <a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code UiAutomatorTestCase}</a> 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.</p>
<p>Because the <a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code UiAutomatorTestCase}</a> 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 <a href="http://www.junit.org/">junit.org</a> home page.</p>
<p>The first thing your test case should do is access the device that contains the target app. Its also good practice to start the test from the Home screen of the device. From the Home screen (or some other starting location youve 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 <a href="#sample">sample test case</a>.</p>
<h3 id="classes">uiautomator API</h3>
<p>The {@code uiautomator} API is bundled in the {@code uiautomator.jar} file under the {@code &lt;android-sdk&gt;/platforms/} directory. The API includes these key classes that allow you to capture and manipulate UI components on the target app:</p>
<dl>
<DT><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a></DT>
<dd><p>Represents the device state. In your tests, you can call methods on the <a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a> instance to check for the state of various properties, such as current orientation or display size. Your tests also can use the <a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a> 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.</p>
<p>To get an instance of <a href="{@docRoot}tools/help/UiDevice.html">{@code UiDevice}</a> and simulate a Home button press:
<pre>
getUiDevice().pressHome();
</pre></p></dd>
<dt><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a></dt>
<dd>Represents a search criteria to query and get a handle on specific elements in the currently displayed UI.
If more than one matching element is found, the first matching element in the layout hierarchy is returned as the target {@code UiObject}. When constructing a <a href="{@docRoot}tools/help/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}tools/help/uiautomator/UiAutomatorObjectNotFoundException.html">{@code UiAutomatorObjectNotFoundException}</a> is thrown. You can use the <a href="{@docRoot}tools/help/uiautomator/UiSelector.html#childSelector(com.android.uiautomator.core.UiSelector)">{@code childSelector()}</a> method to nest multiple <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> instances. For example, the following code example shows how to 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 {@code Apps}.
<pre>
UiObject appItem = new UiObject(new UiSelector()
.className("android.widget.ListView").instance(1)
.childSelector(new UiSelector().text("Apps")));
</pre>
</dd>
<dt><a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a></dt>
<dd>Represents a UI element. To create a <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instance, use a {@code UiSelector} that describes how to search for, or select, the UI element.
<p>The following code example shows how to construct <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instances that represent a <strong>Cancel</strong> button and a <strong>OK</strong> button in your application.</p>
<pre>
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel"));
UiObject okButton = new UiObject(new UiSelector().text("OK"));
</pre>
<p>You can reuse the <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> 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 <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instance to click on a UI element or query a property.</p>
<p>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.</p>
<pre>
if(okButton.exists() && okButton.isEnabled())
{
okButton.click();
}
</pre>
<p>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:</p>
<pre>
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")
.className("android.widget.Button"));
UiObject okButton = new UiObject(new UiSelector().text("OK")
.className("android.widget.Button"));
</pre>
</dd>
<dt><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a></dt>
<dd>Represents a collection of items, for example songs in a music album or a list of emails in an inbox. Similar to a <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a>, you construct a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> instance by specifying a <a href="{@docRoot}tools/help/UiSelector.html">{@code UiSelector}</a>. The <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> for a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> should search for a UI element that is a container or wrapper of other child UI elements (such as a layout view that contains child UI elements). For example, the following code snippet shows how to construct a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> to represent a video album that is displayed within a {@link android.widget.FrameLayout}:
<pre>
UiCollection videos = new UiCollection(new UiSelector()
.className("android.widget.FrameLayout"));
</pre>
<p>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:</p>
<pre>
int count = videos.getChildCount(new UiSelector()
.className("android.widget.LinearLayout"));
</pre>
<p>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:</p>
<pre>
UiObject video = videos.getChildByText(new UiSelector()
.className("android.widget.LinearLayout"), "Cute Baby Laughing");
video.click();
</pre>
<p>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:</p>
<pre>
UiObject checkBox = video.getChild(new UiSelector()
.className("android.widget.Checkbox"));
if(!checkBox.isSelected()) checkbox.click();
</pre>
</dd>
<dt><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">{@code UiScrollable}</a></dt>
<dd>Represents a scrollable collection of UI elements. You can use the <a href="{@docRoot}tools/help/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>For example, the following code shows how to simulate scrolling down the Settings menu and clicking on an <strong>About tablet</strong> 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>
</dd>
</dl>
<p>For more information about these APIs, see the <a href="{@docRoot}tools/help/uiautomator/index.html">{@code uiautomator}</a> reference.</p>
<h3 id="sample">A sample uiautomator test case</h3>
<p>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 <strong>All Apps</strong> screen, scrolling to the <strong>Settings</strong> app icon, and clicking on the icon to enter the Settings app.</p>
<pre>
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();
// Were 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 buttons
// 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());
}
}
</pre>
<h2 id="builddeploy">Building and Deploying Your uiautomator Tests</h2>
<p>Once you have coded your test, follow these steps to build and deploy your test JAR to your target Android test device:</p>
<ol>
<li>Create the required build configuration files to build the output JAR. To generate the build configuration files, open a terminal and run the following command:
<pre>&lt;android-sdk&gt;/tools/android uitest-project -n &lt;name&gt; -t 1 -p &lt;path&gt;</pre>
The {@code &lt;name&gt;} is the name of the project that contains your {@code uiautomator} test source files, and the {@code &lt;path&gt;} is the path to the corresponding project directory.
</li>
<LI>From the command line, set the {@code ANDROID_HOME} variable:
<ul>
<li>In Windows:
<pre>set ANDROID_HOME=&lt;path_to_your_sdk&gt;</pre>
</li>
<li>In UNIX:
<pre>export ANDROID_HOME=&lt;path_to_your_sdk&gt;</pre>
</li>
</ul>
</LI>
<li>Go to the project directory where your {@code build.xml} file is located and build your test JAR. <pre>ant build</pre></li>
<li>Deploy your generated test JAR file to the test device by using the {@code adb push} command: <pre>adb push &lt;path_to_output_jar&gt; /data/local/tmp/</pre>
<p>Heres an example: <pre>adb push ~/dev/workspace/LaunchSettings/bin/LaunchSettings.jar /data/local/tmp/</pre></p>
</li>
</ol>
<h2 id="running">Running uiautomator Tests</h2>
<p>Heres 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:</p>
<pre>adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings</pre>
<p>To learn more about the syntax, subcommands, and options for {@code uiautomator}, see the <a href="{@docRoot}tools/help/uiautomator/index.html">{@code uiautomator}</a> reference.</p>
<h2 id="bestpractices">Best Practices</h2>
<p>Here are some best practices for functional UI testing with the {@code uiautomator} framework: </p>
<ul>
<LI>Ensure that you validate the same UI functions on your application across the various types of devices that your application might run on (for example, devices with different screen densities).</LI>
<li>You should also test your UI against common scenarios such as in-coming phone calls, network interruptions, and user-initiated switching to other applications on the device.</li>
</ul>

View File

@@ -92,6 +92,10 @@
<li>
<a href="<?cs var:toroot?>tools/testing/testing_accessibility.html">
<span class="en">Accessibility Testing</span></a>
</li>
<li>
<a href="<?cs var:toroot?>tools/testing/testing_ui.html">
<span class="en">UI Testing</span></a>
</li>
<li>
<a href="<?cs var:toroot ?>tools/testing/what_to_test.html">
@@ -166,6 +170,20 @@ class="en">MonkeyRunner</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/systrace.html">Systrace</a></li>
<li><a href="<?cs var:toroot ?>tools/help/gltracer.html">Tracer for OpenGL ES</a></li>
<li><a href="<?cs var:toroot ?>tools/help/traceview.html">Traceview</a></li>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/uiautomator/index.html"><span class="en">uiautomator</span></a></div>
<ul>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/IAutomationSupport.html"><span class="en">IAutomationSupport</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiAutomatorTestCase.html"><span class="en">UiAutomatorTestCase</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiCollection.html"><span class="en">UiCollection</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiDevice.html"><span class="en">UiDevice</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiObject.html"><span class="en">UiObject</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiObjectNotFoundException.html"><span class="en">UiObjectNotFoundException</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiScrollable.html"><span class="en">UiScrollable</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiSelector.html"><span class="en">UiSelector</span></a></li>
<li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiWatcher.html"><span class="en">UiWatcher</span></a></li>
</ul>
</li>
<li><a href="<?cs var:toroot ?>tools/help/zipalign.html">zipalign</a></li>
</ul>
</li>