1# Instrumentation Targeting an Application: A Complete Example
2
3[TOC]
4
5If you are new to Android platform development, you might find this complete
6example of adding a brand new instrumentation test from scratch useful to
7demonstrate the typical workflow involved.
8
9Note that this guide assumes that you already have some knowledge in the
10platform source tree workflow. If not, please refer to
11https://source.android.com/source/requirements. The example
12covered here is writing an new instrumentation test with target package set at
13its own test application package. If you are unfamiliar with the concept, please
14read through the [testing basics](../basics/index.md) page.
15
16This guide uses the follow test to serve as an sample:
17
18*   frameworks/base/packages/Shell/tests
19
20It's recommended to browse through the code first to get a rough impression
21before proceeding.
22
23## Deciding on a Source Location
24
25Because the instrumentation test will be targeting an application, the convention
26is to place the test source code in a `tests` directory under the root of your
27component source directory in platform source tree.
28
29See more discussions about source location in the [end-to-end example for
30self-instrumenting tests](instr-self-e2e.md#location).
31
32## Makefile
33
34Each new test module must have a makefile to direct the build system with module
35metadata, compile time depdencies and packaging instructions.
36
37frameworks/base/packages/Shell/tests/Android.mk
38
39A snapshot is included here for convenience:
40
41```makefile
42LOCAL_PATH := $(call my-dir)
43include $(CLEAR_VARS)
44
45LOCAL_MODULE_TAGS := tests
46
47LOCAL_SRC_FILES := $(call all-java-files-under, src)
48
49LOCAL_JAVA_LIBRARIES := android.test.runner
50
51LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator junit legacy-android-test
52
53LOCAL_PACKAGE_NAME := ShellTests
54LOCAL_INSTRUMENTATION_FOR := Shell
55
56LOCAL_COMPATIBILITY_SUITE := device-tests
57
58LOCAL_CERTIFICATE := platform
59include $(BUILD_PACKAGE)
60```
61
62Some select remarks on the makefile:
63
64```makefile
65LOCAL_MODULE_TAGS := tests
66```
67
68This setting declares the module as a test module, which will instruct the build
69system to automatically skip proguard stripping, since that's typically
70problematic for tests.
71
72```makefile
73LOCAL_CERTIFICATE := platform
74```
75
76This setting instructs the build system to sign the test application package
77with the platform certificate. This is because for a test application package to
78be able to instrument on the targeted application package, these two packages
79must be signed with the same certificate; otherwise allowing packages to be
80instrumented on arbitrarily would be a security concern. To find out the signing
81certificate of the application packge you are testing, look for
82`LOCAL_CERTIFICATE` in its `Android.mk`; and if there isn't one, simply skip
83this field in your test application makefile as well.
84
85```makefile
86LOCAL_JAVA_LIBRARIES := android.test.runner
87```
88
89This setting tells the build system to put Java library `android.test.runner` on
90classpath during compilation, as opposed to statically incorporating the library
91into the current package. This is typically done for Java code that is
92referenced by the code in current package, and will be automatically placed on
93package classpath at runtime. In the context of tests for application, strictly
94speaking, both framework APIs and code in application under test fall into this
95category, however, the former is done via implicit rules by build system at
96compile time and by framework at runtime, and the latter is done via
97`LOCAL_INSTRUMENTATION_FOR` (see below) at compile time and via
98`android:targetPackage` (see below) in manifest by instrumentation framework at
99runtime.
100
101```makefile
102LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator junit legacy-android-test
103```
104
105This setting instructs the build system to incorporate the contents of the named
106modules into the resulting apk of current module. This means that each named
107module is expected to produce a `.jar` file, and its content will be used for
108resolving classpath references during compile time, as well as incorporated into
109the resulting apk.
110
111
112The platform source tree also included other useful testing frameworks such as
113`ub-uiautomator`, `easymock` and so on.
114
115```makefile
116LOCAL_PACKAGE_NAME := ShellTests
117```
118
119This setting is required if `BUILD_PACKAGE` when used later: it gives a name to
120your module, and the resulting apk will be named the same and with a `.apk`
121suffix, e.g. in this case, resulting test apk is named as
122`ShellTests.apk`. In addition, this also defines a make target name
123for your module, so that you can use `make [options] <LOCAL_PACKAGE_NAME>` to
124build your test module and all its dependencies.
125
126```makefile {# LOCAL_INSTRUMENTATION_FOR}
127LOCAL_INSTRUMENTATION_FOR := Shell
128```
129
130As mentioned, during execution of an instrumentation test, the application under
131test is restarted with the instrumentation code injected for execution. The test
132can reference any classes and its instances of the application under test. This
133means that the test code may contain references to classes defined by the
134application under test, so during compile time, the build system needs to
135properly resolve such references. This setting provides the module name of
136application under test, which should match the `LOCAL_PACKAGE_NAME` of in the
137makefile for your application. At compile time, the build system will try to
138look up the intermediate files for the named module, and use them on the
139classpath for the Java compiler.
140
141```makefile
142LOCAL_COMPATIBILITY_SUITE := device-tests
143```
144
145This line builds the testcase as part of the device-tests suite, which is
146meant to target a specific device and not a general ABI. If only the ABI
147needs to be targetted, it can be swapped with 'general-tests'.
148
149```makefile
150include $(BUILD_PACKAGE)
151```
152
153This includes a core makefile in build system that performs the necessary steps
154to generate an apk based on the settings provided by the preceding variables.
155The generated apk will be named after `LOCAL_PACKAGE_NAME`, e.g.
156`SettingsGoogleUnitTests.apk`. And if `tests` is used as `LOCAL_MODULE_TAGS` and
157there are no other customizations, you should be able to find your test apk in:
158
159*   `${OUT}/data/app/<LOCAL_PACKAGE_NAME>/<LOCAL_PACKAGE_NAME>.apk`
160
161e.g. `${OUT}/data/app/ShellTests/ShellTests.apk`
162
163## Manifest file
164
165Just like a regular application, each instrumentation test module needs a
166manifest file. If you name the file as `AndroidManifest.xml` and provide it next
167to `Android.mk` for your test tmodule, it will get included automatically by the
168`BUILD_PACKAGE` core makefile.
169
170Before proceeding further, it's highly recommended to go through the external
171[documentation on manifest file](https://developer.android.com/guide/topics/manifest/manifest-intro.html)
172first.
173
174This gives an overview of basic components of a manifest file and their
175functionalities.
176
177Latest version of the manifest file for the sample gerrit change can be accessed
178at:
179https://android.googlesource.com/platform/frameworks/base/+/master/packages/Shell/tests/AndroidManifest.xml
180
181A snapshot is included here for convenience:
182
183```xml
184<manifest xmlns:android="http://schemas.android.com/apk/res/android"
185    package="com.android.shell.tests">
186
187    <application>
188        <uses-library android:name="android.test.runner" />
189
190        <activity
191            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
192            android:label="ActionSendMultipleConsumer"
193            android:theme="@android:style/Theme.NoDisplay"
194            android:noHistory="true"
195            android:excludeFromRecents="true">
196            <intent-filter>
197                <action android:name="android.intent.action.SEND_MULTIPLE" />
198                <category android:name="android.intent.category.DEFAULT" />
199                <data android:mimeType="*/*" />
200            </intent-filter>
201        </activity>
202    </application>
203
204    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
205        android:targetPackage="com.android.shell"
206        android:label="Tests for Shell" />
207
208</manifest>
209```
210
211Some select remarks on the manifest file:
212
213```xml
214<manifest xmlns:android="http://schemas.android.com/apk/res/android"
215    package="com.android.shell.tests">
216```
217
218The `package` attribute is the application package name: this is the unique
219identifier that the Android application framework uses to identify an
220application (or in this context: your test application). Each user in the system
221can only install one application with that package name.
222
223Since this is a test application package, independent from the application
224package under test, a different package name must be used: one common convention
225is to add a suffix `.test`.
226
227Furthermore, this `package` attribute is the same as what
228[`ComponentName#getPackageName()`](https://developer.android.com/reference/android/content/ComponentName.html#getPackageName\(\))
229returns, and also the same you would use to interact with various `pm` sub
230commands via `adb shell`.
231
232Please also note that although the package name is typically in the same style
233as a Java package name, it actually has very few things to do with it. In other
234words, your application (or test) package may contain classes with any package
235names, though on the other hand, you could opt for simplicity and have your top
236level Java package name in your application or test identical to the application
237package name.
238
239```xml
240<uses-library android:name="android.test.runner" />
241```
242
243This is required for all Instrumentation tests since the related classes are
244packaged in a separate framework jar library file, therefore requires additional
245classpath entries when the test package is invoked by application framework.
246
247```xml
248android:targetPackage="com.android.shell"
249```
250
251This sets the target package of the instrumentation to `com.android.shell.tests`.
252When the instrumentation is invoked via `am instrument` command, the framework
253restarts `com.android.shell.tests` process, and injects instrumentation code into
254the process for test execution. This also means that the test code will have
255access to all the class instances running in the application under test and may
256be able to manipulate state depends on the test hooks exposed.
257
258## Test Configuration File
259
260In order to simplify test execution, you also need write a test configuration
261file for Android's test harness, [TradeFederation](https://source.android.com/devices/tech/test_infra/tradefed/).
262
263The test configuration can specify special device setup options and default
264arguments to supply the test class.
265
266The config can be found:
267frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.javast.java
268
269A snapshot is included here for convenience:
270
271```xml
272<configuration description="Runs Tests for Shell.">
273    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
274        <option name="test-file-name" value="ShellTests.apk" />
275    </target_preparer>
276
277    <option name="test-suite-tag" value="apct" />
278    <option name="test-tag" value="ShellTests" />
279    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
280        <option name="package" value="com.android.shell.tests" />
281        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
282    </test>
283</configuration>
284```
285
286Some select remarks on the test configuration file:
287
288```xml
289<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
290  <option name="test-file-name" value="ShellTests.apk"/>
291</target_preparer>
292```
293This tells TradeFederation to install the ShellTests.apk onto the target
294device using a specified target_preparer. There are many target preparers
295available to developers in TradeFederation and these can be used to ensure
296the device is setup properly prior to test execution.
297
298```xml
299<test class="com.android.tradefed.testtype.AndroidJUnitTest">
300  <option name="package" value="com.android.shell.tests"/>
301  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
302</test>
303```
304This specifies the TradeFederation test class to use to execute the test and
305passes in the package on the device to be executed and the test runner
306framework which is JUnit in this case.
307
308Look here for more information on [Test Module Configs](test-config.md)
309
310## JUnit4 Features
311
312Using `android-support-test` library as test runner enables adoptation of new
313JUnit4 style test classes, and the sample gerrit change contains some very basic
314use of its features.
315
316Latest source code for the sample gerrit change can be accessed at:
317frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.javast.java
318
319While testing patterns are usually specific to component teams, there are some
320generally useful usage patterns.
321
322```java
323@SmallTest
324@RunWith(AndroidJUnit4.class)
325public final class FeatureFactoryImplTest {
326```
327
328A significant difference in JUnit4 is that tests are no longer required to
329inherit from a common base test class; instead, you write tests in plain Java
330classes and use annotation to indicate certain test setup and constraints. In
331this example, we are instructing that this class should be run as an Android
332JUnit4 test.
333
334The `@SmallTest` annotation specified a test size for the entire test class: all
335test methods added into this test class inherit this test size annotation.
336pre test class setup, post test tear down, and post test class tear down:
337similar to `setUp` and `tearDown` methods in JUnit4.
338`Test` annotation is used for annotating the actual test.
339
340**Important**: the test methods themselves are annotated with `@Test`
341annotation; and note that for tests to be executed via APCT, they must be
342annotated with test sizes. Such annotation may be applied at method scope, or
343class scope.
344
345```java
346    @Before
347    public void setup() {
348    ...
349    @Test
350    public void testGetProvider_shouldCacheProvider() {
351    ...
352```
353
354The `@Before` annotation is used on methods by JUnit4 to perform pre test setup.
355Although not used in this example, there's also `@After` for post test teardown.
356Similarly, the `@BeforeClass` and `@AfterClass` annotations are can be used on
357methods by JUnit4 to perform setup before executing all tests in a test class,
358and teardown afterwards. Note that the class-scope setup and teardown methods
359must be static.
360
361As for the test methods, unlike in earlier version of JUnit, they no longer need
362to start the method name with `test`, instead, each of them must be annotated
363with `@Test`. As usual, test methods must be public, declare no return value,
364take no parameters, and may throw exceptions.
365
366```java
367        Context context = InstrumentationRegistry.getTargetContext();
368```
369
370Because the JUnit4 tests no longer require a common base class, it's no longer
371necessary to obtain `Context` instances via `getContext()` or
372`getTargetContext()` via base class methods; instead, the new test runner
373manages them via [`InstrumentationRegistry`](https://developer.android.com/reference/android/support/test/InstrumentationRegistry.html)
374where contextual and environmental setup created by instrumentation framework is
375stored. Through this class, you can also call:
376
377*   `getInstrumentation()`: the instance to the `Instrumentation` class
378*   `getArguments()`: the command line arguments passed to `am instrument` via
379    `-e <key> <value>`
380
381## Build & Test Locally
382
383Follow these [Instructions](instrumentation.md)
384