• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Creating Functional Tests
2trainingnavtop=true
3@jd:body
4
5<!-- This is the training bar -->
6<div id="tb-wrapper">
7<div id="tb">
8
9<h2>This lesson teaches you to</h2>
10<ol>
11   <li><a href="#test_methods">Add Test Method to Validate Functional Behavior</a>
12   <ol>
13      <li><a href="#activitymonitor">Set Up an ActivityMonitor</a></li>
14      <li><a href="#keyinput">Send Keyboard Input Using Instrumentation</a></li>
15   </ol>
16   </li>
17</ol>
18
19<h2>Try it out</h2>
20<div class="download-box">
21 <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
22class="button">Download the demo</a>
23 <p class="filename">AndroidTestingFun.zip</p>
24</div>
25
26</div>
27</div>
28<p>Functional testing involves verifying that individual application
29components work together as expected by the user. For example, you can create a
30functional test to verify that an {@link android.app.Activity} correctly
31launches a target {@link android.app.Activity} when the user performs a UI
32interaction.</p>
33
34<p>To create a functional test for your {@link android.app.Activity}, your test
35class should extend {@link android.test.ActivityInstrumentationTestCase2}.
36Unlike {@link android.test.ActivityUnitTestCase},
37tests in {@link android.test.ActivityInstrumentationTestCase2} can
38communicate with the Android system and send keyboard input and click events to
39the UI.</p>
40
41<p>For a complete test case example, take a look at
42{@code SenderActivityTest.java} in the sample app.</p>
43
44<h2 id="test_methods">Add Test Method to Validate Functional Behavior</h2>
45<p id="test_goals">Your functional testing goals might include:</p>
46<ul>
47<li>Verifying that a target {@link android.app.Activity} is started when a
48UI control is pushed in the sender {@link android.app.Activity}.</li>
49<li>Verifying that the target {@link android.app.Activity} displays the
50correct data based on the user's input in the sender
51{@link android.app.Activity}.</li>
52</ul>
53<p>You might implement your test method like this:</p>
54
55<pre>
56&#64;MediumTest
57public void testSendMessageToReceiverActivity() {
58    final Button sendToReceiverButton = (Button)
59            mSenderActivity.findViewById(R.id.send_message_button);
60
61    final EditText senderMessageEditText = (EditText)
62            mSenderActivity.findViewById(R.id.message_input_edit_text);
63
64    // Set up an ActivityMonitor
65    ...
66
67    // Send string input value
68    ...
69
70    // Validate that ReceiverActivity is started
71    ...
72
73    // Validate that ReceiverActivity has the correct data
74    ...
75
76    // Remove the ActivityMonitor
77    ...
78}
79</pre>
80<p>The test waits for an {@link android.app.Activity} that matches this monitor,
81otherwise returns null after a timeout elapses. If {@code ReceiverActivity} was
82started, the {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}
83that you set
84up earlier receives a hit. You can use the assertion methods to verify that
85the {@code ReceiverActivity} is indeed started, and that the hit count on the
86{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} incremented
87as expected.</p>
88
89<h2 id="activitymonitor">Set up an ActivityMonitor</h2>
90<p>To monitor a single {@link android.app.Activity} in your application, you
91can register an {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}.
92The {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} is
93notified by the system whenever an {@link android.app.Activity} that matches your criteria is started.
94If a match is found, the monitor’s hit count is updated.</p>
95<p>Generally, to use an
96{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}, you should:</p>
97<ol>
98<li>Retrieve the {@link android.app.Instrumentation} instance for your test
99case by using the
100{@link android.test.InstrumentationTestCase#getInstrumentation()} method.</li>
101<li>Add an instance of {@link android.app.Instrumentation.ActivityMonitor} to
102the current instrumentation using one of the {@link android.app.Instrumentation}
103{@code addMonitor()} methods. The match criteria can be specified as an
104{@link android.content.IntentFilter} or a class name string.</li>
105<li>Wait for the {@link android.app.Activity} to start.</li>
106<li>Verify that the monitor hits were incremented.</li>
107<li>Remove the monitor.</li>
108</ol>
109<p>For example:</p>
110<pre>
111// Set up an ActivityMonitor
112ActivityMonitor receiverActivityMonitor =
113        getInstrumentation().addMonitor(ReceiverActivity.class.getName(),
114        null, false);
115
116// Validate that ReceiverActivity is started
117TouchUtils.clickView(this, sendToReceiverButton);
118ReceiverActivity receiverActivity = (ReceiverActivity)
119        receiverActivityMonitor.waitForActivityWithTimeout(TIMEOUT_IN_MS);
120assertNotNull("ReceiverActivity is null", receiverActivity);
121assertEquals("Monitor for ReceiverActivity has not been called",
122        1, receiverActivityMonitor.getHits());
123assertEquals("Activity is of wrong type",
124        ReceiverActivity.class, receiverActivity.getClass());
125
126// Remove the ActivityMonitor
127getInstrumentation().removeMonitor(receiverActivityMonitor);
128</pre>
129
130<h2 id="keyinput">Send Keyboard Input Using Instrumentation</h2>
131<p>If your {@link android.app.Activity} has an {@link android.widget.EditText}
132field, you might want to test that users can enter values into the
133{@link android.widget.EditText} object.</p>
134<p>Generally, to send a string input value to an {@link android.widget.EditText}
135object in {@link android.test.ActivityInstrumentationTestCase2}, you should:</p>
136<ol>
137<li>Use the {@link android.app.Instrumentation#runOnMainSync(java.lang.Runnable) runOnMainSync()}
138method to run the {@link android.view.View#requestFocus()} call synchronously
139in a loop. This way, the UI thread is blocked until focus is received.</li>
140<li>Call {@link android.app.Instrumentation#waitForIdleSync()} method to wait
141for the main thread to become idle (that is, have no more events to process).</li>
142<li>Send a text string to the {@link android.widget.EditText} by calling
143{@link android.app.Instrumentation#sendStringSync(java.lang.String)
144sendStringSync()} and pass your input string as the parameter.</p>
145</ol>
146<p>For example:</p>
147<pre>
148// Send string input value
149getInstrumentation().runOnMainSync(new Runnable() {
150    &#64;Override
151    public void run() {
152        senderMessageEditText.requestFocus();
153    }
154});
155getInstrumentation().waitForIdleSync();
156getInstrumentation().sendStringSync("Hello Android!");
157getInstrumentation().waitForIdleSync();
158</pre>
159
160
161
162
163
164
165
166
167