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