Starting March 27, 2025, we recommend using android-latest-release instead of aosp-main to build and contribute to AOSP. For more information, see Changes to AOSP.
Stay organized with collections
Save and categorize content based on your preferences.
When an instrumentation test is started, its target package is
restarted with instrumentation code injected and initiated for execution. One
exception is that the target package here can't be the Android application
framework itself, such as the package android, because doing so leads to the
paradoxical situation where Android framework would need to be restarted, which
is what supports the system functions, including the instrumentation itself.
This means that an instrumentation test cannot inject itself into Android
framework, a.k.a. the system server, for execution. In order to test the Android
framework, the test code can invoke only public API surfaces, or those exposed
using Android Interface Definition Language
AIDL
available in the platform source tree. For this category of tests, it's not meaningful to target any particular package. Therefore, it's customary for such
instrumentations to be declared to target its own test application package, as
defined in its own tag of AndroidManifest.xml.
Depending on the requirements, test application packages in this category may
also:
Bundle activities needed for testing.
Share the user ID with the system.
Be signed with the platform key.
Be compiled against the framework source rather than the public SDK.
This category of instrumentation tests is sometimes referred to as
self-instrumentation. Here are some examples of self-instrumentation tests in
the platform source:
The example covered here is writing a new instrumentation test with target
package set at its own test application package. This guide uses the following
test to serve as an example:
It's recommended to browse through the code first to get a rough impression
before proceeding.
Decide on a source location
Typically your team will already have an established pattern of places to check
in code, and places to add tests. Most teams own a single git repository, or
share one with other teams but have a dedicated sub directory that contains
component source code.
Assuming the root location for your component source is at , most components have src and tests folders under it, and some
additional files such as Android.mk (or broken up into additional .mk files),
the manifest file AndroidManifest.xml, and the test configuration file
'AndroidTest.xml'.
Since you are adding a brand new test, you'll probably need to create the
tests directory next to your component src, and populate it with content.
In some cases, your team might have further directory structures under tests
due to the need to package different suites of tests into individual apks. And
in this case, you'll need to create a new sub directory under tests.
Regardless of the structure, you'll end up populating the tests directory or
the newly created sub directory with files similar to what's in
instrumentation directory in the sample gerrit change. The details of each
file are explained later in this document.
Manifest file
As with an app project, each instrumentation test module requires a
manifest file called AndroidManifest.xml. To automatically include
this file using theBUILD_PACKAGE core makefile, provide this file next to the
Android.mk file for your test module.
If you aren't familiar with the AndroidManifest.xml file, refer to the
App Manifest Overview
The package attribute is the application package name: this is the unique
identifier that the Android application framework uses to identify an
application (or in this context: your test application). Each user in the system
can only install one application with that package name.
Furthermore, this package attribute is the same as what
ComponentName#getPackageName()
returns, and also the same you would use to interact with various pm sub
commands use adb shell.
Note that although the package name is typically in the same style
as a Java package name, it actually has very few things to do with it. In other
words, your application (or test) package may contain classes with any package
names, though on the other hand, you could opt for simplicity and have your top
level Java package name in your application or test identical to the application
package name.
android:sharedUserId="android.uid.system"
This declares that at installation time, this APK file should be granted the
same user ID, i.e. runtime identity, as the core platform. Note that this is
dependent on the apk being signed with same certificate as the core platform
(see LOCAL_CERTIFICATE in a previous section), yet they are different
concepts:
some permissions or APIs are signature protected, which requires same
signing certificate
some permissions or APIs requires the system user identity of the caller,
which requires the calling package to share user ID with system, if it's a
separate package from core platform itself
android:name="android.test.runner"/>
This is required for all Instrumentation tests since the related classes are
packaged in a separate framework JAR library file, therefore requires additional
classpath entries when the test package is invoked by application framework.
You might have noticed that the targetPackage here is declared the same as the
package attribute declared in the manifest tag of this file. As mentioned in
testing basics, this category of instrumentation test are
typically intended for testing framework APIs, so it's not very meaningful for
them to have a specific targeted application package, other then itself.
Simple configuration file
Each new test module must have a configuration file to direct
the build system with module metadata, compile-time dependencies and packaging
instructions. In most cases, the Soong-based, Blueprint file option is
sufficient. For details, see
Simple Test Configuration.
Complex configuration file
For these more complex cases, you also need to write a test configuration
file for Android's test harness,
Trade Federation.
This tells Trade Federation to install the HelloWorldTests.apk onto the target
device using a specified target_preparer. There are many target preparers
available to developers in Trade Federation and these can be used to ensure
the device is setup properly prior to test execution.
This specifies the Trade Federation test class to use to execute the test and
passes in the package on the device to be executed and the test runner
framework which is JUnit in this case.
While testing patterns are usually specific to component teams, there are some
generally useful usage patterns.
@RunWith(JUnit4.class)publicclassHelloWorldTest{
A significant difference in JUnit4 is that tests are no longer required to
inherit from a common base test class; instead, you write tests in plain Java
classes and use annotation to indicate certain test setup and constraints. In
this example, we are instructing that this class should be run as a JUnit4 test.
The @Before and @After annotations are used on methods by JUnit4 to perform
pre test setup and post test teardown. Similarly, the @BeforeClass and
@AfterClass annotations are used on methods by JUnit4 to perform setup before
executing all tests in a test class, and teardown afterwards. Note that the
class-scope setup and teardown methods must be static. As for the test methods,
unlike in earlier version of JUnit, they no longer need to start the method name
with test, instead, each of them must be annotated with @Test. As usual,
test methods must be public, declare no return value, take no parameters, and
may throw exceptions.
Instrumentation class access
Although not covered in the basic hello world example, it's fairly common for an
Android test to require access Instrumentation instance: this is the core API
interface that provides access to application contexts, activity lifecycle
related test APIs and more.
Because the JUnit4 tests no longer require a common base class, it's no longer
necessary to obtain Instrumentation instance via
InstrumentationTestCase#getInstrumentation(), instead, the new test runner
manages it via InstrumentationRegistry
where contextual and environmental setup created by instrumentation framework is
stored.
To access the instance of Instrumentation class, simply call static method
getInstrumentation() on InstrumentationRegistry class:
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-04-04 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-04-04 UTC."],[],[]]