diff options
Diffstat (limited to 'docs/html/training/activity-testing/activity-functional-testing.jd')
| -rw-r--r-- | docs/html/training/activity-testing/activity-functional-testing.jd | 166 |
1 files changed, 166 insertions, 0 deletions
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> + + + + + + + + |
