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    &#64;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&#64;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 &#64;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&#64;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&#64;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 &#64;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 &#64;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 &#64;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 &#64;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 &#64;SmallTest}. Longer running tests (100 milliseconds or
206more) are usually marked as {@code &#64;MediumTest}s or {@code &#64;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