1page.title=Testing UI Components 2trainingnavtop=true 3 4@jd:body 5 6<!-- This is the training bar --> 7<div id="tb-wrapper"> 8<div id="tb"> 9 10<h2>This lesson teaches you to</h2> 11<ol> 12 <li><a href="#testcase">Create a Test Case for UI Testing with Instrumentation</a> 13 <li><a href="#test_method">Add Test Methods to Verify UI Behavior</a> 14 <ol> 15 <li><a href="#verify_button_display">Verify Button Layout Parameters</a></li> 16 <li><a href="#verify_TextView">Verify TextView Layout Parameters</a></li> 17 <li><a href="#verify_button_behavior">Verify Button Behavior</a></li> 18 </ol> 19 </li> 20 <li><a href="#annotations">Apply Test Annotations</a></li> 21</ol> 22 23<h2>Try it out</h2> 24<div class="download-box"> 25 <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip" 26class="button">Download the demo</a> 27 <p class="filename">AndroidTestingFun.zip</p> 28</div> 29 30</div> 31</div> 32 33<p>Typically, your {@link android.app.Activity} includes user interface 34components (such as buttons, editable text fields, checkboxes, and pickers) to 35allow users to interact with your Android application. This lesson shows how 36you can test an {@link android.app.Activity} with a simple push-button UI. You 37can use the same general steps to test other, more sophisticated types of UI 38components.</p> 39 40<p class="note"><strong>Note:</strong> The type of UI testing in this lesson is 41called <em>white-box testing</em> because you have the 42source code for the application that you want to test. The Android 43<a href="{@docRoot}tools/testing/testing_android.html#Instrumentation">Instrumentation</a> 44framework is suitable for creating white-box tests for UI components within an 45application. An alternative type of UI testing is <em>black-box testing</em>, 46where you may not have access to the application source. This type of testing 47is useful when you want to test how your app interacts with other apps or with 48the system. Black-box testing is not covered in this training. To learn more 49about how to perform black-box testing on your Android apps, see the 50<a href="{@docRoot}tools/testing/testing_ui.html">UI Testing guide</a>. 51<p>For a complete test case example, take a look at 52{@code ClickFunActivityTest.java} in the sample app.</p> 53 54<h2 id="testcase">Create a Test Case for UI Testing with Instrumentation</h2> 55<p>When testing an {@link android.app.Activity} that has a user interface (UI), 56the {@link android.app.Activity} under test runs in the UI thread. However, the 57test application itself runs in a separate thread in the same process as the 58application under test. This means that your test app can reference objects 59from the UI thread, but if it attempts to change properties on those objects or 60send events to the UI thread, you will usually get a {@code WrongThreadException} 61error.</p> 62<p>To safely inject {@link android.content.Intent} objects into your 63{@link android.app.Activity} or run test methods on the UI thread, you can 64extend your test class to use {@link android.test.ActivityInstrumentationTestCase2}. 65To learn more about how to run test methods on the UI thread, see 66<a href="{@docRoot}tools/testing/activity_testing.html#RunOnUIThread">Testing 67on the UI thread</a>.</p> 68 69<h3 id="fixture">Set Up Your Test Fixture</h3> 70<p>When setting up the test fixture for UI testing, you should specify the 71<a href="{@docRoot}guide/topics/ui/ui-events.html#TouchMode">touch mode</a> 72in your {@link junit.framework.TestCase#setUp()} method. Setting the touch mode 73to {@code true} prevents the UI control from taking focus when you click it 74programmatically in the test method later (for example, a button UI will just 75fire its on-click listener). Make sure that you call 76{@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode()} 77before calling {@link android.test.ActivityInstrumentationTestCase2#getActivity()}. 78</p> 79<p>For example:</ap> 80<pre> 81public class ClickFunActivityTest 82 extends ActivityInstrumentationTestCase2<ClickFunActivity> { 83 ... 84 @Override 85 protected void setUp() throws Exception { 86 super.setUp(); 87 88 setActivityInitialTouchMode(true); 89 90 mClickFunActivity = getActivity(); 91 mClickMeButton = (Button) 92 mClickFunActivity 93 .findViewById(R.id.launch_next_activity_button); 94 mInfoTextView = (TextView) 95 mClickFunActivity.findViewById(R.id.info_text_view); 96 } 97} 98</pre> 99 100<h2 id="test_methods">Add Test Methods to Validate UI Behavior</h2> 101<p id="test_goals">Your UI testing goals might include:</p> 102<ul> 103<li>Verifying that a button is displayed with the correct layout when the 104{@link android.app.Activity} is launched.</li> 105<li>Verifying that a {@link android.widget.TextView} is initially hidden.</li> 106<li>Verifying that a {@link android.widget.TextView} displays the expected string 107when a button is pushed.</li> 108</ul> 109<p>The following section demonstrates how you can implement test methods 110to perform these verifications.</p> 111 112<h3 id="verify_button_display">Verify Button Layout Parameters</h3> 113<p>You might add a test method like this to verify that a button is displayed 114correctly in your {@link android.app.Activity}:</p> 115<pre> 116@MediumTest 117public void testClickMeButton_layout() { 118 final View decorView = mClickFunActivity.getWindow().getDecorView(); 119 120 ViewAsserts.assertOnScreen(decorView, mClickMeButton); 121 122 final ViewGroup.LayoutParams layoutParams = 123 mClickMeButton.getLayoutParams(); 124 assertNotNull(layoutParams); 125 assertEquals(layoutParams.width, WindowManager.LayoutParams.MATCH_PARENT); 126 assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT); 127} 128</pre> 129 130<p>In the {@link android.test.ViewAsserts#assertOnScreen(android.view.View,android.view.View) assertOnScreen()} 131method call, you should pass in the root view and the view that you are 132expecting to be present on the screen. If the expected view is not found in the 133root view, the assertion method throws an {@link junit.framework.AssertionFailedError} 134exception, otherwise the test passes.</p> 135<p>You can also verify that the layout of a {@link android.widget.Button} is 136correct by getting a reference to its {@link android.view.ViewGroup.LayoutParams} 137object, then call assertion methods to verify that the 138{@link android.widget.Button} object's width and height attributes match the 139expected values.</p> 140<p>The {@code @MediumTest} annotation specifies how the test is categorized, 141relative to its absolute execution time. To learn more about using test size 142annotations, see <a href="#annotations">Apply Test Annotations</a>.</p> 143 144<h3 id="verify_TextView">Verify TextView Layout Parameters</h3> 145<p>You might add a test method like this to verify that a 146{@link android.widget.TextView} initially appears hidden in 147your {@link android.app.Activity}:</p> 148<pre> 149@MediumTest 150public void testInfoTextView_layout() { 151 final View decorView = mClickFunActivity.getWindow().getDecorView(); 152 ViewAsserts.assertOnScreen(decorView, mInfoTextView); 153 assertTrue(View.GONE == mInfoTextView.getVisibility()); 154} 155</pre> 156<p>You can call {@link android.view.Window#getDecorView()} to get a reference 157to the decor view for the {@link android.app.Activity}. The decor view is the 158top-level ViewGroup ({@link android.widget.FrameLayout}) view in the layout 159hierarchy.</p> 160 161<h3 id="verify_button_behavior">Verify Button Behavior</h3> 162<p>You can use a test method like this to verify that a 163{@link android.widget.TextView} becomes visible when a 164{@link android.widget.Button} is pushed:</p> 165 166<pre> 167@MediumTest 168public void testClickMeButton_clickButtonAndExpectInfoText() { 169 String expectedInfoText = mClickFunActivity.getString(R.string.info_text); 170 TouchUtils.clickView(this, mClickMeButton); 171 assertTrue(View.VISIBLE == mInfoTextView.getVisibility()); 172 assertEquals(expectedInfoText, mInfoTextView.getText()); 173} 174</pre> 175 176<p>To programmatically click a {@link android.widget.Button} in your 177test, call {@link android.test.TouchUtils#clickView(android.test.InstrumentationTestCase,android.view.View) clickView()}. 178You must pass in a reference to the test case that is being run and a reference 179to the {@link android.widget.Button} to manipulate.</p> 180 181<p class="note"><strong>Note: </strong>The {@link android.test.TouchUtils} 182helper class provides convenience methods for simulating touch interactions 183with your application. You can use these methods to simulate clicking, tapping, 184and dragging of Views or the application screen.</p> 185<p class="caution"><strong>Caution: </strong>The {@link android.test.TouchUtils} 186methods are designed to send events to the UI thread safely from the test thread. 187You should not run {@link android.test.TouchUtils} directly in the UI thread or 188any test method annotated with {@code @UIThread}. Doing so might 189raise the {@code WrongThreadException}.</p> 190 191<h2 id="annotations">Apply Test Annotations</h2> 192<p>The following annotations can be applied to indicate the size of a test 193method:</p> 194<dl> 195<dt>{@link 196android.test.suitebuilder.annotation.SmallTest @SmallTest}</dt> 197<dd>Marks a test that should run as part of the small tests.</dd> 198<dt>{@link 199android.test.suitebuilder.annotation.MediumTest @MediumTest}</dt> 200<dd>Marks a test that should run as part of the medium tests.</dd> 201<dt>{@link android.test.suitebuilder.annotation.LargeTest @LargeTest}</dt> 202<dd>Marks a test that should run as part of the large tests.</dd> 203</dl> 204<p>Typically, a short running test that take only a few milliseconds should be 205marked as a {@code @SmallTest}. Longer running tests (100 milliseconds or 206more) are usually marked as {@code @MediumTest}s or {@code @LargeTest}s, 207depending on whether the test accesses resources on the local system only or 208remote resources over a network. For guidance on using test size annotations, 209see this <a href="https://plus.sandbox.google.com/+AndroidDevelopers/posts/TPy1EeSaSg8">Android Tools Protip</a>.</p> 210<p>You can mark up your test methods with other test annotations to control 211how the tests are organized and run. For more information on other annotations, 212see the {@link java.lang.annotation.Annotation} class reference.</p> 213 214 215 216 217