| 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> |
| |
| |
| |
| |