Home | History | Annotate | Download | only in activity-testing
      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     &#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
    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 &#64;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 &#64;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 &#64;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 &#64;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 &#64;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 &#64;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 &#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
    205 marked as a {@code &#64;SmallTest}. Longer running tests (100 milliseconds or
    206 more) are usually marked as {@code &#64;MediumTest}s or {@code &#64;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