1 page.title=Testing UI Components 2 trainingnavtop=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" 26 class="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 34 components (such as buttons, editable text fields, checkboxes, and pickers) to 35 allow users to interact with your Android application. This lesson shows how 36 you can test an {@link android.app.Activity} with a simple push-button UI. You 37 can use the same general steps to test other, more sophisticated types of UI 38 components.</p> 39 40 <p class="note"><strong>Note:</strong> The type of UI testing in this lesson is 41 called <em>white-box testing</em> because you have the 42 source code for the application that you want to test. The Android 43 <a href="{@docRoot}tools/testing/testing_android.html#Instrumentation">Instrumentation</a> 44 framework is suitable for creating white-box tests for UI components within an 45 application. An alternative type of UI testing is <em>black-box testing</em>, 46 where you may not have access to the application source. This type of testing 47 is useful when you want to test how your app interacts with other apps or with 48 the system. Black-box testing is not covered in this training. To learn more 49 about 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), 56 the {@link android.app.Activity} under test runs in the UI thread. However, the 57 test application itself runs in a separate thread in the same process as the 58 application under test. This means that your test app can reference objects 59 from the UI thread, but if it attempts to change properties on those objects or 60 send events to the UI thread, you will usually get a {@code WrongThreadException} 61 error.</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 64 extend your test class to use {@link android.test.ActivityInstrumentationTestCase2}. 65 To learn more about how to run test methods on the UI thread, see 66 <a href="{@docRoot}tools/testing/activity_testing.html#RunOnUIThread">Testing 67 on 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> 72 in your {@link junit.framework.TestCase#setUp()} method. Setting the touch mode 73 to {@code true} prevents the UI control from taking focus when you click it 74 programmatically in the test method later (for example, a button UI will just 75 fire its on-click listener). Make sure that you call 76 {@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode()} 77 before calling {@link android.test.ActivityInstrumentationTestCase2#getActivity()}. 78 </p> 79 <p>For example:</ap> 80 <pre> 81 public 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 107 when a button is pushed.</li> 108 </ul> 109 <p>The following section demonstrates how you can implement test methods 110 to 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 114 correctly in your {@link android.app.Activity}:</p> 115 <pre> 116 @MediumTest 117 public 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()} 131 method call, you should pass in the root view and the view that you are 132 expecting to be present on the screen. If the expected view is not found in the 133 root view, the assertion method throws an {@link junit.framework.AssertionFailedError} 134 exception, otherwise the test passes.</p> 135 <p>You can also verify that the layout of a {@link android.widget.Button} is 136 correct by getting a reference to its {@link android.view.ViewGroup.LayoutParams} 137 object, then call assertion methods to verify that the 138 {@link android.widget.Button} object's width and height attributes match the 139 expected values.</p> 140 <p>The {@code @MediumTest} annotation specifies how the test is categorized, 141 relative to its absolute execution time. To learn more about using test size 142 annotations, 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 147 your {@link android.app.Activity}:</p> 148 <pre> 149 @MediumTest 150 public 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 157 to the decor view for the {@link android.app.Activity}. The decor view is the 158 top-level ViewGroup ({@link android.widget.FrameLayout}) view in the layout 159 hierarchy.</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 168 public 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 177 test, call {@link android.test.TouchUtils#clickView(android.test.InstrumentationTestCase,android.view.View) clickView()}. 178 You must pass in a reference to the test case that is being run and a reference 179 to the {@link android.widget.Button} to manipulate.</p> 180 181 <p class="note"><strong>Note: </strong>The {@link android.test.TouchUtils} 182 helper class provides convenience methods for simulating touch interactions 183 with your application. You can use these methods to simulate clicking, tapping, 184 and dragging of Views or the application screen.</p> 185 <p class="caution"><strong>Caution: </strong>The {@link android.test.TouchUtils} 186 methods are designed to send events to the UI thread safely from the test thread. 187 You should not run {@link android.test.TouchUtils} directly in the UI thread or 188 any test method annotated with {@code @UIThread}. Doing so might 189 raise 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 193 method:</p> 194 <dl> 195 <dt>{@link 196 android.test.suitebuilder.annotation.SmallTest @SmallTest}</dt> 197 <dd>Marks a test that should run as part of the small tests.</dd> 198 <dt>{@link 199 android.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 205 marked as a {@code @SmallTest}. Longer running tests (100 milliseconds or 206 more) are usually marked as {@code @MediumTest}s or {@code @LargeTest}s, 207 depending on whether the test accesses resources on the local system only or 208 remote resources over a network. For guidance on using test size annotations, 209 see 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 211 how the tests are organized and run. For more information on other annotations, 212 see the {@link java.lang.annotation.Annotation} class reference.</p> 213 214 215 216 217