am 40765a4a: am 2ef3952d: cherrypick from jb-mr2-docs docs: Android training for Activity testing. Change-Id: I7167732c849d5a4a36c808cc852ddfcdc8e60bd7

* commit '40765a4a5300914e8c7ce7ed6397cec7ab8d78a1':
  cherrypick from jb-mr2-docs docs: Android training for Activity testing. Change-Id: I7167732c849d5a4a36c808cc852ddfcdc8e60bd7
This commit is contained in:
quddusc
2013-08-29 11:57:52 -07:00
committed by Android Git Automerger
10 changed files with 952 additions and 0 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,227 @@
page.title=Creating and Running a Test Case
trainingnavtop=true
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#testcase">Create a Test Case for Activity Testing</a>
<ol>
<li><a href="#fixture">Set Up Your Test Fixture</a></li>
<li><a href="#preconditions">Add Test Preconditions</a></li>
<li><a href="#test_method">Add Test Methods to Verify Your Activity</a></li>
</ol>
</li>
<li><a href="#build_run">Build and Run Your Test</a></li>
</ol>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}tools/testing/testing_android.html">Testing
Fundamentals</a></li>
</ul>
</div>
</div>
<p>In order to verify that there are no regressions in the layout design and
functional behavior in your application, it's important to
create a test for each {@link android.app.Activity} in your application. For
each test, you need to create the individual parts of a test case, including
the test fixture, preconditions test method, and {@link android.app.Activity}
test methods. You can then run your test to get a test report. If any test
method fails, this might indicate a potential defect in your code.</p>
<p class="note"><strong>Note:</strong> In the Test-Driven Development (TDD)
approach, instead of writing most or all of your app code up-front and then
running tests later in the development cycle, you would progressively write
just enough production code to satisfy your test dependencies, update your
test cases to reflect new functional requirements, and iterate repeatedly this
way.</p>
<h2 id="testcase">Create a Test Case</h2>
<p>{@link android.app.Activity} tests are written in a structured way.
Make sure to put your tests in a separate package, distinct from the code under
test.</p>
<p>By convention, your test package name should follow the same name as the
application package, suffixed with <strong>".tests"</strong>. In the test package
you created, add the Java class for your test case. By convention, your test case
name should also follow the same name as the Java or Android class that you
want to test, but suffixed with <strong>“Test”</strong>.</p>
<p>To create a new test case in Eclipse:</p>
<ol type="a">
<li>In the Package Explorer, right-click on the {@code /src} directory for
your test project and select <strong>New &gt; Package</strong>.</li>
<li>Set the <strong>Name</strong> field to
{@code &lt;your_app_package_name&gt;.tests} (for example,
{@code com.example.android.testingfun.tests}) and click
<strong>Finish</strong>.</li>
<li>Right-click on the test package you created, and select
<strong>New &gt; Class</strong>.</li>
<li>Set the <strong>Name</strong> field to
{@code &lt;your_app_activity_name&gt;Test} (for example,
{@code MyFirstTestActivityTest}) and click <strong>Finish</strong>.</li>
</ol>
<h3 id="fixture">Set Up Your Test Fixture</h3>
<p>A <em>test fixture</em> consists of objects that must be initialized for
running one or more tests. To set up the test fixture, you can override the
{@link junit.framework.TestCase#setUp()} and
{@link junit.framework.TestCase#tearDown()} methods in your test. The
test runner automatically runs {@link junit.framework.TestCase#setUp()} before
running any other test methods, and {@link junit.framework.TestCase#tearDown()}
at the end of each test method execution. You can use these methods to keep
the code for test initialization and clean up separate from the tests methods.
</p>
<p>To set up your test fixture in Eclipse:</p>
<ol>
<li>In the Package Explorer, double-click on the test case that you created
earlier to bring up the Eclipse Java editor, then modify your test case class
to extend one of the sub-classes of {@link android.test.ActivityTestCase}.
<p>For example:</p>
<pre>
public class MyFirstTestActivityTest
extends ActivityInstrumentationTestCase2&lt;MyFirstTestActivity&gt; {
</pre>
</li>
<li>Next, add the constructor and {@link junit.framework.TestCase#setUp()}
methods to your test case, and add variable declarations for the
{@link android.app.Activity} that you want to test.</p>
<p>For example:</p>
<pre>
public class MyFirstTestActivityTest
extends ActivityInstrumentationTestCase2&lt;MyFirstTestActivity&gt; {
private MyFirstTestActivity mFirstTestActivity;
private TextView mFirstTestText;
public MyFirstTestActivityTest() {
super(MyFirstTestActivity.class);
}
&#64;Override
protected void setUp() throws Exception {
super.setUp();
mFirstTestActivity = getActivity();
mFirstTestText =
(TextView) mFirstTestActivity
.findViewById(R.id.my_first_test_text_view);
}
}
</pre>
<p>The constructor is invoked by the test runner to instantiate the test
class, while the {@link junit.framework.TestCase#setUp()} method is invoked by
the test runner before it runs any tests in the test class.</p>
</li>
</ol>
<p>Typically, in the {@link junit.framework.TestCase#setUp()} method, you
should:</p>
<ul>
<li>Invoke the superclass constructor for
{@link junit.framework.TestCase#setUp()}, which is required by JUnit.</li>
<li>Initialize your test fixture state by:
<ul>
<li>Defining the instance variables that store the state of the fixture.</li>
<li>Creating and storing a reference to an instance of the
{@link android.app.Activity} under test.</li>
<li>Obtaining a reference to any UI components in the
{@link android.app.Activity} that you want to test.</li>
</ul>
</ul>
<p>You can use the
{@link android.test.ActivityInstrumentationTestCase2#getActivity()} method to
get a reference to the {@link android.app.Activity} under test.</p>
<h3 id="preconditions">Add Test Preconditions</h3>
<p>As a sanity check, it is good practice to verify that the test fixture has
been set up correctly, and the objects that you want to test have been correctly
instantiated or initialized. That way, you wont have to see
tests failing because something was wrong with the setup of your test fixture.
By convention, the method for verifying your test fixture is called
{@code testPreconditions()}.</p>
<p>For example, you might want to add a {@code testPreconditons()} method like
this to your test case:</p>
<pre>
public void testPreconditions() {
assertNotNull(“mFirstTestActivity is null”, mFirstTestActivity);
assertNotNull(“mFirstTestText is null”, mFirstTestText);
}
</pre>
<p>The assertion methods are from the JUnit {@link junit.framework.Assert}
class. Generally, you can use assertions to
verify if a specific condition that you want to test is true.
<ul>
<li>If the condition is false, the assertion method throws an
{@link android.test.AssertionFailedError} exception, which is then typically
reported by the test runner. You can provide a string in the first argument of
your assertion method to give some contextual details if the assertion fails.</li>
<li>If the condition is true, the test passes.</li>
</ul>
<p>In both cases, the test runner proceeds to run the other test methods in the
test case.</p>
<h3 id="test_method">Add Test Methods to Verify Your Activity</h3>
<p>Next, add one or more test methods to verify the layout and functional
behavior of your {@link android.app.Activity}.</p>
<p>For example, if your {@link android.app.Activity} includes a
{@link android.widget.TextView}, you can add a test method like this to check
that it has the correct label text:</p>
<pre>
public void testMyFirstTestTextView_labelText() {
final String expected =
mFirstTestActivity.getString(R.string.my_first_test);
final String actual = mFirstTestText.getText().toString();
assertEquals(expected, actual);
}
</pre>
<p>The {@code testMyFirstTestTextView_labelText()} method simply checks that the
default text of the {@link android.widget.TextView} that is set by the layout
is the same as the expected text defined in the {@code strings.xml} resource.</p>
<p class="note"><strong>Note:</strong> When naming test methods, you can use
an underscore to separate what is being tested from the specific case being
tested. This style makes it easier to see exactly what cases are being tested.</p>
<p>When doing this type of string value comparison, its good practice to read
the expected string from your resources, instead of hardcoding the string in
your comparison code. This prevents your test from easily breaking whenever the
string definitions are modified in the resource file.</p>
<p>To perform the comparison, pass both the expected and actual strings as
arguments to the
{@link junit.framework.Assert#assertEquals(java.lang.String, java.lang.String) assertEquals()}
method. If the values are not the same, the assertion will throw an
{@link junit.framework.AssertionFailedError} exception.</p>
<p>If you added a {@code testPreconditions()} method, put your test methods
after the {@code testPreconditions()} definition in your Java class.</p>
<p>For a complete test case example, take a look at
{@code MyFirstTestActivityTest.java} in the sample app.</p>
<h2 id="build_run">Build and Run Your Test</h2>
<p>You can build and run your test easily from the Package Explorer in
Eclipse.</p>
<p>To build and run your test:</p>
<ol>
<li>Connect an Android device to your machine. On the device or emulator, open
the <strong>Settings</strong> menu, select <strong>Developer options</strong>
and make sure that USB debugging is enabled.</li>
<li>In the Project Explorer, right-click on the test class that you created
earlier and select <strong>Run As &gt; Android Junit Test</strong>.</li>
<li>In the Android Device Chooser dialog, select the device that you just
connected, then click <strong>OK</strong>.</li>
<li>In the JUnit view, verify that the test passes with no errors or failures.</li>
</ol>
<p>For example, if the test case passes with no errors, the result should look
like this:</p>
<img src="{@docRoot}images/training/activity-testing_lesson2_MyFirstTestActivityTest_result.png" alt="" />
<p class="img-caption">
<strong>Figure 1.</strong> Result of a test with no errors.
</p>

View File

@@ -0,0 +1,166 @@
page.title=Creating Functional Tests
trainingnavtop=true
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#test_methods">Add Test Method to Validate Functional Behavior</a>
<ol>
<li><a href="#activitymonitor">Set Up an ActivityMonitor</a></li>
<li><a href="#keyinput">Send Keyboard Input Using Instrumentation</a></li>
</ol>
</li>
</ol>
<h2>Try it out</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
class="button">Download the demo</a>
<p class="filename">AndroidTestingFun.zip</p>
</div>
</div>
</div>
<p>Functional testing involves verifying that individual application
components work together as expected by the user. For example, you can create a
functional test to verify that an {@link android.app.Activity} correctly
launches a target {@link android.app.Activity} when the user performs a UI
interaction.</p>
<p>To create a functional test for your {@link android.app.Activity}, your test
class should extend {@link android.test.ActivityInstrumentationTestCase2}.
Unlike {@link android.test.ActivityUnitTestCase},
tests in {@link android.test.ActivityInstrumentationTestCase2} can
communicate with the Android system and send keyboard input and click events to
the UI.</p>
<p>For a complete test case example, take a look at
{@code SenderActivityTest.java} in the sample app.</p>
<h2 id="test_methods">Add Test Method to Validate Functional Behavior</h2>
<p id="test_goals">Your functional testing goals might include:</p>
<ul>
<li>Verifying that a target {@link android.app.Activity} is started when a
UI control is pushed in the sender {@link android.app.Activity}.</li>
<li>Verifying that the target {@link android.app.Activity} displays the
correct data based on the user's input in the sender
{@link android.app.Activity}.</li>
</ul>
<p>You might implement your test method like this:</p>
<pre>
&#64;MediumTest
public void testSendMessageToReceiverActivity() {
final Button sendToReceiverButton = (Button)
mSenderActivity.findViewById(R.id.send_message_button);
final EditText senderMessageEditText = (EditText)
mSenderActivity.findViewById(R.id.message_input_edit_text);
// Set up an ActivityMonitor
...
// Send string input value
...
// Validate that ReceiverActivity is started
...
// Validate that ReceiverActivity has the correct data
...
// Remove the ActivityMonitor
...
}
</pre>
<p>The test waits for an {@link android.app.Activity} that matches this monitor,
otherwise returns null after a timeout elapses. If {@code ReceiverActivity} was
started, the {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}
that you set
up earlier receives a hit. You can use the assertion methods to verify that
the {@code ReceiverActivity} is indeed started, and that the hit count on the
{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} incremented
as expected.</p>
<h2 id="activitymonitor">Set up an ActivityMonitor</h2>
<p>To monitor a single {@link android.app.Activity} in your application, you
can register an {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}.
The {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} is
notified by the system whenever an {@link android.app.Activity} that matches your criteria is started.
If a match is found, the monitors hit count is updated.</p>
<p>Generally, to use an
{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}, you should:</p>
<ol>
<li>Retrieve the {@link android.app.Instrumentation} instance for your test
case by using the
{@link android.test.InstrumentationTestCase#getInstrumentation()} method.</li>
<li>Add an instance of {@link android.app.Instrumentation.ActivityMonitor} to
the current instrumentation using one of the {@link android.app.Instrumentation}
{@code addMonitor()} methods. The match criteria can be specified as an
{@link android.content.IntentFilter} or a class name string.</li>
<li>Wait for the {@link android.app.Activity} to start.</li>
<li>Verify that the monitor hits were incremented.</li>
<li>Remove the monitor.</li>
</ol>
<p>For example:</p>
<pre>
// Set up an ActivityMonitor
ActivityMonitor receiverActivityMonitor =
getInstrumentation().addMonitor(ReceiverActivity.class.getName(),
null, false);
// Validate that ReceiverActivity is started
TouchUtils.clickView(this, sendToReceiverButton);
ReceiverActivity receiverActivity = (ReceiverActivity)
receiverActivityMonitor.waitForActivityWithTimeout(TIMEOUT_IN_MS);
assertNotNull("ReceiverActivity is null", receiverActivity);
assertEquals("Monitor for ReceiverActivity has not been called",
1, receiverActivityMonitor.getHits());
assertEquals("Activity is of wrong type",
ReceiverActivity.class, receiverActivity.getClass());
// Remove the ActivityMonitor
getInstrumentation().removeMonitor(receiverActivityMonitor);
</pre>
<h2 id="keyinput">Send Keyboard Input Using Instrumentation</h2>
<p>If your {@link android.app.Activity} has an {@link android.widget.EditText}
field, you might want to test that users can enter values into the
{@link android.widget.EditText} object.</p>
<p>Generally, to send a string input value to an {@link android.widget.EditText}
object in {@link android.test.ActivityInstrumentationTestCase2}, you should:</p>
<ol>
<li>Use the {@link android.app.Instrumentation#runOnMainSync(java.lang.Runnable) runOnMainSync()}
method to run the {@link android.view.View#requestFocus()} call synchronously
in a loop. This way, the UI thread is blocked until focus is received.</li>
<li>Call {@link android.app.Instrumentation#waitForIdleSync()} method to wait
for the main thread to become idle (that is, have no more events to process).</li>
<li>Send a text string to the {@link android.widget.EditText} by calling
{@link android.app.Instrumentation#sendStringSync(java.lang.String)
sendStringSync()} and pass your input string as the parameter.</p>
</ol>
<p>For example:</p>
<pre>
// Send string input value
getInstrumentation().runOnMainSync(new Runnable() {
&#64;Override
public void run() {
senderMessageEditText.requestFocus();
}
});
getInstrumentation().waitForIdleSync();
getInstrumentation().sendStringSync("Hello Android!");
getInstrumentation().waitForIdleSync();
</pre>

View File

@@ -0,0 +1,216 @@
page.title=Testing UI Components
trainingnavtop=true
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#testcase">Create a Test Case for UI Testing with Instrumentation</a>
<li><a href="#test_method">Add Test Methods to Verify UI Behavior</a>
<ol>
<li><a href="#verify_button_display">Verify Button Layout Parameters</a></li>
<li><a href="#verify_TextView">Verify TextView Layout Parameters</a></li>
<li><a href="#verify_button_behavior">Verify Button Behavior</a></li>
</ol>
</li>
<li><a href="#annotations">Apply Test Annotations</a></li>
</ol>
<h2>Try it out</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
class="button">Download the demo</a>
<p class="filename">AndroidTestingFun.zip</p>
</div>
</div>
</div>
<p>Typically, your {@link android.app.Activity} includes user interface
components (such as buttons, editable text fields, checkboxes, and pickers) to
allow users to interact with your Android application. This lesson shows how
you can test an {@link android.app.Activity} with a simple push-button UI. You
can use the same general steps to test other, more sophisticated types of UI
components.</p>
<p class="note"><strong>Note:</strong> The type of UI testing in this lesson is
called <em>white-box testing</em> because you have the
source code for the application that you want to test. The Android
<a href="{@docRoot}tools/testing/testing_android.html#Instrumentation">Instrumentation</a>
framework is suitable for creating white-box tests for UI components within an
application. An alternative type of UI testing is <em>black-box testing</em>,
where you may not have access to the application source. This type of testing
is useful when you want to test how your app interacts with other apps or with
the system. Black-box testing is not covered in this training. To learn more
about how to perform black-box testing on your Android apps, see the
<a href="{@docRoot}tools/testing/testing_ui.html">UI Testing guide</a>.
<p>For a complete test case example, take a look at
{@code ClickFunActivityTest.java} in the sample app.</p>
<h2 id="testcase">Create a Test Case for UI Testing with Instrumentation</h2>
<p>When testing an {@link android.app.Activity} that has a user interface (UI),
the {@link android.app.Activity} under test runs in the UI thread. However, the
test application itself runs in a separate thread in the same process as the
application under test. This means that your test app can reference objects
from the UI thread, but if it attempts to change properties on those objects or
send events to the UI thread, you will usually get a {@code WrongThreadException}
error.</p>
<p>To safely inject {@link android.content.Intent} objects into your
{@link android.app.Activity} or run test methods on the UI thread, you can
extend your test class to use {@link android.test.ActivityInstrumentationTestCase2}.
To learn more about how to run test methods on the UI thread, see
<a href="{@docRoot}tools/testing/activity_testing.html#RunOnUIThread">Testing
on the UI thread</a>.</p>
<h3 id="fixture">Set Up Your Test Fixture</h3>
<p>When setting up the test fixture for UI testing, you should specify the
<a href="{@docRoot}guide/topics/ui/ui-events.html#TouchMode">touch mode</a>
in your {@link junit.framework.TestCase#setUp()} method. Setting the touch mode
to {@code true} prevents the UI control from taking focus when you click it
programmatically in the test method later (for example, a button UI will just
fire its on-click listener). Make sure that you call
{@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode()}
before calling {@link android.test.ActivityInstrumentationTestCase2#getActivity()}.
</p>
<p>For example:</ap>
<pre>
public class ClickFunActivityTest
extends ActivityInstrumentationTestCase2<ClickFunActivity> {
...
&#64;Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(true);
mClickFunActivity = getActivity();
mClickMeButton = (Button)
mClickFunActivity
.findViewById(R.id.launch_next_activity_button);
mInfoTextView = (TextView)
mClickFunActivity.findViewById(R.id.info_text_view);
}
}
</pre>
<h2 id="test_methods">Add Test Methods to Validate UI Behavior</h2>
<p id="test_goals">Your UI testing goals might include:</p>
<ul>
<li>Verifying that a button is displayed with the correct layout when the
{@link android.app.Activity} is launched.</li>
<li>Verifying that a {@link android.widget.TextView} is initially hidden.</li>
<li>Verifying that a {@link android.widget.TextView} displays the expected string
when a button is pushed.</li>
</ul>
<p>The following section demonstrates how you can implement test methods
to perform these verifications.</p>
<h3 id="verify_button_display">Verify Button Layout Parameters</h3>
<p>You might add a test method like this to verify that a button is displayed
correctly in your {@link android.app.Activity}:</p>
<pre>
&#64;MediumTest
public void testClickMeButton_layout() {
final View decorView = mClickFunActivity.getWindow().getDecorView();
ViewAsserts.assertOnScreen(decorView, mClickMeButton);
final ViewGroup.LayoutParams layoutParams =
mClickMeButton.getLayoutParams();
assertNotNull(layoutParams);
assertEquals(layoutParams.width, WindowManager.LayoutParams.MATCH_PARENT);
assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT);
}
</pre>
<p>In the {@link android.test.ViewAsserts#assertOnScreen(android.view.View,android.view.View) assertOnScreen()}
method call, you should pass in the root view and the view that you are
expecting to be present on the screen. If the expected view is not found in the
root view, the assertion method throws an {@link junit.framework.AssertionFailedError}
exception, otherwise the test passes.</p>
<p>You can also verify that the layout of a {@link android.widget.Button} is
correct by getting a reference to its {@link android.view.ViewGroup.LayoutParams}
object, then call assertion methods to verify that the
{@link android.widget.Button} object's width and height attributes match the
expected values.</p>
<p>The {@code &#64;MediumTest} annotation specifies how the test is categorized,
relative to its absolute execution time. To learn more about using test size
annotations, see <a href="#annotations">Apply Test Annotations</a>.</p>
<h3 id="verify_TextView">Verify TextView Layout Parameters</h3>
<p>You might add a test method like this to verify that a
{@link android.widget.TextView} initially appears hidden in
your {@link android.app.Activity}:</p>
<pre>
&#64;MediumTest
public void testInfoTextView_layout() {
final View decorView = mClickFunActivity.getWindow().getDecorView();
ViewAsserts.assertOnScreen(decorView, mInfoTextView);
assertTrue(View.GONE == mInfoTextView.getVisibility());
}
</pre>
<p>You can call {@link android.view.Window#getDecorView()} to get a reference
to the decor view for the {@link android.app.Activity}. The decor view is the
top-level ViewGroup ({@link android.widget.FrameLayout}) view in the layout
hierarchy.</p>
<h3 id="verify_button_behavior">Verify Button Behavior</h3>
<p>You can use a test method like this to verify that a
{@link android.widget.TextView} becomes visible when a
{@link android.widget.Button} is pushed:</p>
<pre>
&#64;MediumTest
public void testClickMeButton_clickButtonAndExpectInfoText() {
String expectedInfoText = mClickFunActivity.getString(R.string.info_text);
TouchUtils.clickView(this, mClickMeButton);
assertTrue(View.VISIBLE == mInfoTextView.getVisibility());
assertEquals(expectedInfoText, mInfoTextView.getText());
}
</pre>
<p>To programmatically click a {@link android.widget.Button} in your
test, call {@link android.test.TouchUtils#clickView(android.test.InstrumentationTestCase,android.view.View) clickView()}.
You must pass in a reference to the test case that is being run and a reference
to the {@link android.widget.Button} to manipulate.</p>
<p class="note"><strong>Note: </strong>The {@link android.test.TouchUtils}
helper class provides convenience methods for simulating touch interactions
with your application. You can use these methods to simulate clicking, tapping,
and dragging of Views or the application screen.</p>
<p class="caution"><strong>Caution: </strong>The {@link android.test.TouchUtils}
methods are designed to send events to the UI thread safely from the test thread.
You should not run {@link android.test.TouchUtils} directly in the UI thread or
any test method annotated with {@code &#64;UIThread}. Doing so might
raise the {@code WrongThreadException}.</p>
<h2 id="annotations">Apply Test Annotations</h2>
<p>The following annotations can be applied to indicate the size of a test
method:</p>
<dl>
<dt>{@link
android.test.suitebuilder.annotation.SmallTest &#64;SmallTest}</dt>
<dd>Marks a test that should run as part of the small tests.</dd>
<dt>{@link
android.test.suitebuilder.annotation.MediumTest &#64;MediumTest}</dt>
<dd>Marks a test that should run as part of the medium tests.</dd>
<dt>{@link android.test.suitebuilder.annotation.LargeTest &#64;LargeTest}</dt>
<dd>Marks a test that should run as part of the large tests.</dd>
</dl>
<p>Typically, a short running test that take only a few milliseconds should be
marked as a {@code &#64;SmallTest}. Longer running tests (100 milliseconds or
more) are usually marked as {@code &#64;MediumTest}s or {@code &#64;LargeTest}s,
depending on whether the test accesses resources on the local system only or
remote resources over a network. For guidance on using test size annotations,
see this <a href="https://plus.sandbox.google.com/+AndroidDevelopers/posts/TPy1EeSaSg8">Android Tools Protip</a>.</p>
<p>You can mark up your test methods with other test annotations to control
how the tests are organized and run. For more information on other annotations,
see the {@link java.lang.annotation.Annotation} class reference.</p>

View File

@@ -0,0 +1,134 @@
page.title=Creating Unit Tests
trainingnavtop=true
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#testcase">Create a Test Case for Activity Unit Testing</a>
<li><a href="#test_method">Validate Launch of Another Activity</a>
</ol>
<h2>Try it out</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
class="button">Download the demo</a>
<p class="filename">AndroidTestingFun.zip</p>
</div>
</div>
</div>
<p>An {@link android.app.Activity} unit test is an excellent way to quickly
verify the state of an {@link android.app.Activity} and its interactions with
other components in isolation (that is, disconnected from the rest of the
system). A unit test generally tests the smallest possible unit of code
(which could be a method, class, or component), without dependencies on system
or network resources. For example, you can write a unit test to check
that an {@link android.app.Activity} has the correct layout or that it
triggers an {@link android.content.Intent} object correctly.</p>
<p>Unit tests are generally not suitable for testing complex UI interaction
events with the system. Instead, you should use
the {@link android.test.ActivityInstrumentationTestCase2} class, as described
in <a href="activity-ui-testing.html">Testing UI Components</a>.</p>
<p>This lesson shows how you can write a unit test to verify that an
{@link android.content.Intent} is triggered to launch another
{@link android.app.Activity}.
Since the test runs in an isolated environment, the
{@link android.content.Intent}
is not actually sent to the Android system, but you can inspect that the
{@link android.content.Intent} object's payload data is accurate.</p>
<p>For a complete test case example, take a look at
{@code LaunchActivityTest.java} in the sample app.</p>
<p class="note"><strong>Note: </strong>To test against system or external
dependencies, you can use mock objects from a mocking
framework and inject them into your unit tests. To learn more about the mocking
framework provided by Android, see
<a href="{@docRoot}tools/testing/testing_android.html#MockObjectClasses}">Mock
Object Classes</a>.</p>
<h2 id="testcase">Create a Test Case for Activity Unit Testing</h2>
<p>The {@link android.test.ActivityUnitTestCase} class provides support for
isolated testing of a single {@link android.app.Activity}. To create a unit
test for your {@link android.app.Activity}, your test class should extend
{@link android.test.ActivityUnitTestCase}.</p>
<p>The {@link android.app.Activity} in an {@link android.test.ActivityUnitTestCase}
is not automatically started by Android Instrumentation. To start the
{@link android.app.Activity} in isolation, you need to explicitly call the
{@link android.test.ActivityUnitTestCase#startActivity(android.content.Intent, android.os.Bundle, java.lang.Object) startActivity()}
method, and pass in the {@link android.content.Intent} to
launch your target {@link android.app.Activity}.</p>
<p>For example:</p>
<pre>
public class LaunchActivityTest
extends ActivityUnitTestCase&lt;LaunchActivity&gt; {
...
&#64;Override
protected void setUp() throws Exception {
super.setUp();
mLaunchIntent = new Intent(getInstrumentation()
.getTargetContext(), LaunchActivity.class);
startActivity(mLaunchIntent, null, null);
final Button launchNextButton =
(Button) getActivity()
.findViewById(R.id.launch_next_activity_button);
}
}
</pre>
<h2 id="test_method">Validate Launch of Another Activity</h2>
<p id="test_goals">Your unit testing goals might include:</p>
<ul>
<li>Verifying that {@code LaunchActivity} fires an
{@link android.content.Intent} when a button is pushed clicked.</li>
<li>Verifying that the launched {@link android.content.Intent} contains the
correct payload data.</li>
</ul>
<p>To verify if an {@link android.content.Intent} was triggered
following the {@link android.widget.Button} click, you can use the
{@link android.test.ActivityUnitTestCase#getStartedActivityIntent()} method.
By using assertion methods, you can verify that the returned
{@link android.content.Intent} is not null, and that it contains the expected
string value to launch the next {@link android.app.Activity}. If both assertions
evaluate to {@code true}, you've successfully verified that the
{@link android.content.Intent} was correctly sent by your
{@link android.app.Activity}.</p>
<p>You might implement your test method like this:</p>
<pre>
&#64;MediumTest
public void testNextActivityWasLaunchedWithIntent() {
startActivity(mLaunchIntent, null, null);
final Button launchNextButton =
(Button) getActivity()
.findViewById(R.id.launch_next_activity_button);
launchNextButton.performClick();
final Intent launchIntent = getStartedActivityIntent();
assertNotNull("Intent was null", launchIntent);
assertTrue(isFinishCalled());
final String payload =
launchIntent.getStringExtra(NextActivity.EXTRAS_PAYLOAD_KEY);
assertEquals("Payload is empty", LaunchActivity.STRING_PAYLOAD, payload);
}
</pre>
<p>Because {@code LaunchActivity} runs in isolation, you cannot use the
{@link android.test.TouchUtils} library to manipulate UI controls. To directly
click a {@link android.widget.Button}, you can call the
{@link android.view.View#performClick()} method instead.</p>

View File

@@ -0,0 +1,68 @@
page.title=Testing Your Android Activity
page.tags="testing"
trainingnavtop=true
startpage=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
<h2>Dependencies and prerequisites</h2>
<ul>
<li>Android 2.2 (API Level 8) or higher.</li>
</ul>
<h2>You Should Also Read</h2>
<ul>
<li><a href="{@docRoot}tools/testing/index.html">Testing
(Developer's Guide)</a></li>
</ul>
</div>
</div>
<p>You should be writing and running tests as part of your Android application
development cycle. Well-written tests can help you to catch bugs early in
development and give you confidence in your code.</p>
<p>A <em>test case</em> defines a set of objects and methods to run multiple
tests independently from each other. Test cases can be organized into
<em>test suites</em> and run programmatically, in a repeatable manner, with
a <em>test runner</em> provided by a testing framework.</p>
<p>The lessons in this class teaches you how to use the Android's custom
testing framework that is based on the popular JUnit framework. You can
write test cases to verify specific behavior in your application, and check for
consistency across different Android devices. Your test cases also serve as a
form of internal code documentation by describing the expected behavior of
app components.</p>
<h2>Lessons</h2>
<!-- Create a list of the lessons in this class along with a short description
of each lesson. These should be short and to the point. It should be clear from
reading the summary whether someone will want to jump to a lesson or not.-->
<dl>
<dt><b><a href="preparing-activity-testing.html">Setting Up Your Test
Environment</a></b></dt>
<dd>Learn how to create your test project.</dd>
<dt><b><a href="activity-basic-testing.html">Creating and Running a Test
Case</a></b></dt>
<dd>Learn how to write test cases to verify the
expected properties of your {@link android.app.Activity}, and run the test
cases with the {@code Instrumentation} test runner provided by the Android
framework.</dd>
<dt><b><a href="activity-ui-testing.html">Testing UI Components</a></b></dt>
<dd>Learn how to test the behavior of specific UI
components in your {@link android.app.Activity}.</dd>
<dt><b><a href="activity-unit-testing.html">Creating Unit Tests</a></b></dt>
<dd>Learn how to how to perform unit testing to
verify the behavior of an Activity in isolation.</dd>
<dt><b><a href="activity-functional-testing.html">Creating Functional Tests</a></b></dt>
<dd>Learn how to perform functional testing to
verify the interaction of multiple Activities.</dd>

View File

@@ -0,0 +1,95 @@
page.title=Setting Up Your Test Environment
trainingnavtop=true
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#eclipse">Set Up Eclipse for Testing</a></li>
<li><a href="#cmdline">Set Up the Command Line Interface for Testing</a></li>
</ol>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}sdk/index.html">Getting the SDK Bundle</a></li>
<li><a href="{@docRoot}tools/testing/testing_eclipse.html">Testing from Eclipse
with ADT</a></li>
<li><a href="{@docRoot}tools/testing/testing_otheride.html">Testing from Other
IDEs</a></li>
</ul>
<h2>Try it out</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
class="button">Download the demo</a>
<p class="filename">AndroidTestingFun.zip</p>
</div>
</div>
</div>
<p>Before you start writing and running your tests, you should set up your test
development environment. This lesson teaches you how to set up the Eclipse
IDE to build and run tests, and how to
build and run tests with the Gradle framework by using the command line
interface.</p>
<p class="note"><strong>Note:</strong> To help you get started, the lessons are
based on Eclipse with the ADT plugin. However, for your own test development, you
are free to use the IDE of your choice or the command-line.</p>
<h2 id="eclipse">Set Up Eclipse for Testing</h2>
<p>Eclipse with the Android Developer Tools (ADT) plugin provides an integrated
development environment for you to create, build, and run Android application
test cases from a graphical user interface (GUI). A convenient feature that
Eclipse provides is the ability to auto-generate a new test project that
corresponds with your Android application project</a>.
<p>To set up your test environment in Eclipse:</p>
<ol>
<li><a href="{@docRoot}sdk/installing/bundle.html">Download and install the
Eclipse ADT plugin</a>, if you havent installed it yet.</li>
<li>Import or create the Android application project that you want to test
against.</li>
<li>Generate a test project that corresponds to the application project under
test. To generate a test project for the app project that you imported:</p>
<ol type="a">
<li>In the Package Explorer, right-click on your app project, then
select <strong>Android Tools</strong> &gt; <strong>New Test Project</strong>.</li>
<li>In the New Android Test Project wizard, set the property
values for your test project then click <strong>Finish</strong>.</li>
</ol>
</li>
</ol>
<p>You should now be able to create, build, and run test
cases from your Eclipse environment. To learn how to perform these tasks in
Eclipse, proceed to <a href="activity-basic-testing.html">Creating and Running
a Test Case</a>.</p>
<h2 id="cmdline">Set Up the Command Line Interface for Testing</h2>
<p>If you are using Gradle version 1.6 or higher as your build environment, you
can build and run your Android application tests from the command line by using
the Gradle Wrapper. Make sure that in your {@code gradle.build} file, the
<a href={@docRoot}guide/topics/manifest/uses-sdk-element.html#min>minSdkVersion</a>
attribute in the {@code defaultConfig} section is set to 8 or higher. You can
refer to the sample {@code gradle.build} file that is
included in the download bundle for this training class.</p>
<p>To run your tests with the Gradle Wrapper:</p>
<ol>
<li>Connect a physical Android device to your machine or launch the Android
Emulator.</li>
<li>Run the following command from your project directory:
<pre>./gradlew build connectedCheck</pre>
</li>
</ol>
<p>To learn more about using Gradle for Android testing, see the
<a href="//tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing">Gradle Plugin User Guide</a>.</p>
<p>To learn more about using command line tools other than Gradle for test
development, see
<a href="{@docRoot}tools/testing/testing_otheride.html">Testing from Other IDEs</a>.</p>

View File

@@ -0,0 +1,7 @@
page.title=Best Practices for Testing
page.trainingcourse=true
@jd:body
<p>These classes and articles provide information about how to
test your Android application.</p>

View File

@@ -1205,6 +1205,45 @@ include the action bar on devices running Android 2.1 or higher."
</li>
<!-- End security and user info -->
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/testing.html">
<span class="small">Best Practices for</span><br/>
Testing
</a>
</div>
<ul>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/activity-testing/index.html"
description="How to test Activities in your Android applications.">
Testing Your Activity
</a></div>
<ul>
<li><a href="<?cs var:toroot ?>training/activity-testing/preparing-activity-testing.html">
<span class="en">Setting Up Your Test Environment</span>
</a>
</li>
<li><a href="<?cs var:toroot ?>training/activity-testing/activity-basic-testing.html">
<span class="en">Creating and Running a Test Case</span>
</a>
</li>
<li><a href="<?cs var:toroot ?>training/activity-testing/activity-ui-testing.html">
<span class="en">Testing UI Components</span>
</a>
</li>
<li><a href="<?cs var:toroot ?>training/activity-testing/activity-unit-testing.html">
<span class="en">Creating Unit Tests</span>
</a>
</li>
<li><a href="<?cs var:toroot ?>training/activity-testing/activity-functional-testing.html">
<span class="en">Creating Functional Tests</span>
</a>
</li>
</ul>
</li>
</ul>
</li>
<!-- End best Testing -->
<li class="nav-section">
<div class="nav-section-header">