diff options
author | quddusc <quddusc@google.com> | 2013-06-21 16:49:46 -0700 |
---|---|---|
committer | quddusc <quddusc@google.com> | 2013-08-29 10:52:49 -0700 |
commit | 2ef3952d8e62b71baca176b3e17315a37facd34a (patch) | |
tree | 5f951ecfb00562efcc925d76775e81187c4473c1 /docs | |
parent | 8236443bdac2ba7c7630ddcc4ce9a18a03fe31a1 (diff) | |
download | frameworks_base-2ef3952d8e62b71baca176b3e17315a37facd34a.zip frameworks_base-2ef3952d8e62b71baca176b3e17315a37facd34a.tar.gz frameworks_base-2ef3952d8e62b71baca176b3e17315a37facd34a.tar.bz2 |
cherrypick from jb-mr2-docs docs: Android training for Activity testing. Change-Id: I7167732c849d5a4a36c808cc852ddfcdc8e60bd7
Change-Id: Idce540108d048d76fc2c4bc37ecf2118b82588c5
Diffstat (limited to 'docs')
-rw-r--r-- | docs/downloads/training/AndroidTestingFun.zip | bin | 0 -> 475029 bytes | |||
-rw-r--r-- | docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png | bin | 0 -> 12854 bytes | |||
-rw-r--r-- | docs/html/training/activity-testing/activity-basic-testing.jd | 227 | ||||
-rw-r--r-- | docs/html/training/activity-testing/activity-functional-testing.jd | 166 | ||||
-rw-r--r-- | docs/html/training/activity-testing/activity-ui-testing.jd | 216 | ||||
-rw-r--r-- | docs/html/training/activity-testing/activity-unit-testing.jd | 134 | ||||
-rw-r--r-- | docs/html/training/activity-testing/index.jd | 68 | ||||
-rw-r--r-- | docs/html/training/activity-testing/preparing-activity-testing.jd | 95 | ||||
-rw-r--r-- | docs/html/training/testing.jd | 7 | ||||
-rw-r--r-- | docs/html/training/training_toc.cs | 39 |
10 files changed, 952 insertions, 0 deletions
diff --git a/docs/downloads/training/AndroidTestingFun.zip b/docs/downloads/training/AndroidTestingFun.zip Binary files differnew file mode 100644 index 0000000..dca5812 --- /dev/null +++ b/docs/downloads/training/AndroidTestingFun.zip diff --git a/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png Binary files differnew file mode 100644 index 0000000..e0e869b --- /dev/null +++ b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png diff --git a/docs/html/training/activity-testing/activity-basic-testing.jd b/docs/html/training/activity-testing/activity-basic-testing.jd new file mode 100644 index 0000000..016289d --- /dev/null +++ b/docs/html/training/activity-testing/activity-basic-testing.jd @@ -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 > Package</strong>.</li> + <li>Set the <strong>Name</strong> field to +{@code <your_app_package_name>.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 > Class</strong>.</li> + <li>Set the <strong>Name</strong> field to +{@code <your_app_activity_name>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<MyFirstTestActivity> { +</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<MyFirstTestActivity> { + + private MyFirstTestActivity mFirstTestActivity; + private TextView mFirstTestText; + + public MyFirstTestActivityTest() { + super(MyFirstTestActivity.class); + } + + @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 won’t 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, it’s 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 > 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> + + + diff --git a/docs/html/training/activity-testing/activity-functional-testing.jd b/docs/html/training/activity-testing/activity-functional-testing.jd new file mode 100644 index 0000000..7c8ff1d --- /dev/null +++ b/docs/html/training/activity-testing/activity-functional-testing.jd @@ -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> +@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 monitor’s 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() { + @Override + public void run() { + senderMessageEditText.requestFocus(); + } +}); +getInstrumentation().waitForIdleSync(); +getInstrumentation().sendStringSync("Hello Android!"); +getInstrumentation().waitForIdleSync(); +</pre> + + + + + + + + diff --git a/docs/html/training/activity-testing/activity-ui-testing.jd b/docs/html/training/activity-testing/activity-ui-testing.jd new file mode 100644 index 0000000..644f3ca --- /dev/null +++ b/docs/html/training/activity-testing/activity-ui-testing.jd @@ -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> { + ... + @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> +@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 @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> +@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> +@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 @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 @SmallTest}</dt> +<dd>Marks a test that should run as part of the small tests.</dd> +<dt>{@link +android.test.suitebuilder.annotation.MediumTest @MediumTest}</dt> +<dd>Marks a test that should run as part of the medium tests.</dd> +<dt>{@link android.test.suitebuilder.annotation.LargeTest @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 @SmallTest}. Longer running tests (100 milliseconds or +more) are usually marked as {@code @MediumTest}s or {@code @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> + + + + diff --git a/docs/html/training/activity-testing/activity-unit-testing.jd b/docs/html/training/activity-testing/activity-unit-testing.jd new file mode 100644 index 0000000..74dcda9 --- /dev/null +++ b/docs/html/training/activity-testing/activity-unit-testing.jd @@ -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<LaunchActivity> { + ... + + @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> +@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> + + + + + + + diff --git a/docs/html/training/activity-testing/index.jd b/docs/html/training/activity-testing/index.jd new file mode 100644 index 0000000..ddede71 --- /dev/null +++ b/docs/html/training/activity-testing/index.jd @@ -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> + diff --git a/docs/html/training/activity-testing/preparing-activity-testing.jd b/docs/html/training/activity-testing/preparing-activity-testing.jd new file mode 100644 index 0000000..c43c9ed --- /dev/null +++ b/docs/html/training/activity-testing/preparing-activity-testing.jd @@ -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 haven’t 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> > <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> + diff --git a/docs/html/training/testing.jd b/docs/html/training/testing.jd new file mode 100644 index 0000000..c55370d --- /dev/null +++ b/docs/html/training/testing.jd @@ -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> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 40c170e..b884620 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -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"> |