Home | History | Annotate | Download | only in development
      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