blob: bfba189f5fd319851dd81094f17d79e1b3151c1f [file] [log] [blame] [view]
# Android Instrumentation Tests
Instrumentation tests are Java tests based on
[`android.app.Instrumentation`](https://developer.android.com/reference/android/app/Instrumentation.html).
They run on a device.
[TOC]
## Writing an instrumentation test
Currently, an instrumentation test is just a JUnit3-style test based on
[android.test.InstrumentationTestCase](https://developer.android.com/reference/android/test/InstrumentationTestCase.html).
(This will change starting in [Android N](https://en.wikipedia.org/wiki/Android_Nougat).)
Writing an instrumentation test case can be simple, e.g.
```java
package org.chromium.sample.test;
import android.test.InstrumentationTestCase;
public class MyInstrumentationTest extends InstrumentationTestCase {
// Note that, because it's a JUnit3-style test, the test method *must*
// start with "test".
public void testTheFirst() {
bool writingInstrumentationTestsCanBeEasy = true;
// InstrumentationTestCase inherits the assert* methods through
// junit.framework.TestCase.
assertTrue(writingInstrumentationTestsCanBeEasy);
}
public void testTheSecond() {
bool writingInstrumentationTestsIsAlwaysEasy = false;
assertFalse(writingInstrumentationTestsIsAlwaysEasy);
}
}
```
After writing a test, you can run it by:
- Adding the file to the relevant gn target if the entire file is new.
Typically, the "relevant gn target" is simply the target containing the
other files in the same directory.
- Rebuild.
- Run the test using the process described [here](/testing/android/docs/todo.md).
## Instrumentation test features
In many cases, Chromium has extended the instrumentation test framework
classes to implement additional features.
### Tracing
Enabling tracing during a test run allows all the function calls involved to be
observed in a visual display (using Chrome's built-in chrome://tracing feature).
To run a test with tracing, add the `--trace-output` flag to the command used to
call the instrumentation test (either running the test_runner.py script, or a
generated binary such as `run_chrome_public_test_apk`). The `--trace-output` flag
takes a filename, which, after the test run, will contain a JSON file readable
by chrome://tracing.
By default, the trace includes only certain function calls important to the test
run, both within the Python test runner framework and the Java code running on
the device. For a more detailed look, add the (no-argument) `--trace-all` flag.
This causes every function called on the Python side to be added to the trace.
### Annotations
Instrumentation tests in Chromium use a wide variety of annotations to control
and manipulate test execution. Some of these are implemented in Chromium, while
others are pulled in from outside. They include:
#### Size annotations
Size annotations are used primarily by the test runner to determine the length
of time to wait before considering a test hung (i.e., its timeout duration).
Several of the annotations are Android APIs from
[android.test.suitebuilder.annotation](https://developer.android.com/reference/android/test/suitebuilder/annotation/package-summary.html)
(prior to [Android N](https://en.wikipedia.org/wiki/Android_Nougat)) or
[android.support.test.filters](https://developer.android.com/reference/android/support/test/filters/package-summary.html)
(starting in Android N). These are all fairly self-explanatory:
- [`@SmallTest`](https://developer.android.com/reference/android/support/test/filters/SmallTest.html) (timeout: **1 minute**)
- [`@MediumTest`](https://developer.android.com/reference/android/support/test/filters/MediumTest.html) (timeout: **3 minutes**)
- [`@LargeTest`](https://developer.android.com/reference/android/support/test/filters/LargeTest.html) (timeout: **5 minutes**)
A few additional size annotations are provided in
[//base](https://chromium.googlesource.com/chromium/src/+/master/base):
- [`@EnormousTest`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java)
(timeout: **10 minutes**) Typically used for tests that require WiFi.
- [`@IntegrationTest`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java)
(timeout: **30 minutes**) Used for tests that run against real services.
- [`@Manual`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java)
(timeout: **10 hours**) Used for manual tests.
Beware that the timeout durations for these annotations are subject to
change, though they rarely do. These values are defined
[here](https://chromium.googlesource.com/chromium/src/+/master/build/android/pylib/local/device/local_device_instrumentation_test_run.py#20).
#### Annotations that disable tests
There are several annotations that control whether or not a test runs.
Some are conditional, others are not.
##### Unconditional disabling
[**@DisabledTest**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java)
unconditionally disables a test.
```java
@DisabledTest(
// Describes why the test is disabled. Typically includes a crbug link.
message = ""
)
```
[**@FlakyTest**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java)
marks a test as flaky. This also unconditionally disables the test, though
tests marked with **@FlakyTest** are explicitly run on some bots.
```java
@FlakyTest(
// Describes why the test is marked flaky. Typically includes a crbug link.
message = ""
)
```
Note that there are Android versions of **@DisabledTest** and **@FlakyTest**
that do not allow message specification. These are no longer used in Chromium.
As alluded to above, tests marked with either **@DisabledTest** or
**@FlakyTest** can be explicitly run via the test runner's
[-A/--annotation](/testing/android/docs/todo.md)
flag. For example, this would run only the tests marked as flaky in
`chrome_public_test_apk`:
```bash
./out/Debug/bin/run_chrome_public_test_apk -A FlakyTest
```
##### Conditional disabling
There are two primary annotation categories that conditionally disable tests:
**@DisableIf** and **@Restriction**. The **@DisableIf** annotations are intended
to temporarily disable a test in certain scenarios where it *should* work but
doesn't. In contrast, the **@Restriction** annotation is intended to
permanently limit a test to specific configurations. It signifies that the test
was not, is not, and will not be intended to run beyond those configurations.
In both cases, conditional disabling manifests as a skipped test.
[**@DisableIf.Build**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#25)
allows for conditional test disabling based on values in
[`android.os.Build`](https://developer.android.com/reference/android/os/Build.html):
```java
@DisableIf.Build(
// Describes why the test is disabled.
message = "",
// Disables the test on SDK levels that match the given conditions.
// Checks against Build.VERSION.SDK_INT.
sdk_is_greater_than = 0,
sdk_is_less_than = Integer.MAX_VALUE,
// Disables the test on devices that support the given ABI
// (e.g. "arm64-v8a"). Checks against:
// - Build.SUPPORTED_ABIS on L+
// - Build.CPU_ABI and Build.CPU_ABI2 otherwise
supported_abis_includes = "",
// Disables the test on devices with hardware that matches the given
// value. Checks against Build.HARDWARE.
hardware_is = "",
// Disables the test on devices with product names that contain the
// given value. Checks against Build.PRODUCT.
product_name_includes = "",
)
```
[**@DisableIf.Device**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#40)
allows for conditional test disabling based on whether
a device is a phone, a tablet, or a "large tablet" as determined by
[org.chromium.ui.base.DeviceFormFactor](https://chromium.googlesource.com/chromium/src/+/master/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java).
This is available to tests in
[//ui](https://chromium.googlesource.com/chromium/src/+/master/ui/)
or code that uses //ui.
```java
@DisableIf.Device(
// Disables the test on devices that match the given type(s) as described
// above.
type = {}
)
```
[**@Restriction**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java)
currently allows for conditional test disabling based on device
type, device performance, internet connectivity, whether Google Play Services is
up to date, and whether the build was an official one.
```java
@Restriction(
// Possible values include:
//
// base:
// - Restriction.RESTRICTION_TYPE_LOW_END_DEVICE
// Restricts the test to low-end devices as determined by SysUtils.isLowEndDevice().
//
// - Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE
// Restricts the test to non-low-end devices as determined by SysUtils.isLowEndDevice().
//
// - Restriction.RESTRICTION_TYPE_INTERNET
// Restricts the test to devices that have an internet connection.
//
// chrome:
// - ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES
// Restricts the test to devices with up-to-date versions of Google Play Services.
//
// - ChromeRestriction.RESTRICTION_TYPE_OFFICIAL_BUILD
// Restricts the test to official builds as determined by ChromeVersionInfo.isOfficialBuild().
//
// ui:
// - UiRestriction.RESTRICTION_TYPE_PHONE
// Restricts the test to phones as determined by DeviceFormFactor.
//
// - UiRestriction.RESTRICTION_TYPE_TABLET
// Restricts the test to tablets as determined by DeviceFormFactor.
value = {}
)
```
[**@MinAndroidSdkLevel**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java)
is similar to **@Restriction** in purpose in that it's
intended to permanently limit a test to only recent versions of Android.
```java
@MinAndroidSdkLevel(
// The minimum SDK level at which this test should be executed. Checks
// against Build.VERSION.SDK_INT.
value = 0
)
```
#### Annotations that affect how a test is run
Several annotations affect how a test is run in interesting or nontrivial ways.
[**@CommandLineFlags.Add**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#46)
and
[**@CommandLineFlags.Remove**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#58)
manipulate Chrome's
command-line flags on a per-test basis (i.e., the flags handled by
[`org.chromium.base.CommandLine`](https://chromium.googlesource.com/chromium/src/+/master/base/android/java/src/org/chromium/base/CommandLine.java) and
[`base::CommandLine`](https://chromium.googlesource.com/chromium/src/+/master/base/command_line.h)).
```java
@CommandLineFlags.Add(
// The flags to add to the command line for this test. These can be
// anything and typically should include the leading dashes (e.g. "--foo").
value = {}
)
@CommandLineFlags.Remove(
// The flags to remove from the command line for this test. These can only
// be flags added via @CommandLineFlags.Add. Flags already present in the
// command-line file on the device are only present in the native
// CommandLine object and cannot be manipulated.
value = {}
)
```
#### Feature annotations
[**@Feature**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java)
has been used inconsistently in Chromium to group tests across
test cases according to the feature they're testing.
```java
@Feature(
// The features associated with this test. These can be anything.
value = {}
)
```
@Feature doesn't have an inherent function, but it can be used to filter tests
via the test runner's
[-A/--annotation](/testing/android/docs/todo.md) and
[-E/--exclude-annotation](/testing/android/docs/todo.md) flags. For example,
this would run only the tests with @Feature annotations containing at least
"Sync" in `chrome_public_test_apk`:
```bash
out/Debug/bin/run_chrome_public_test_apk -A Feature=Sync
```
## Advanced
- [Creating a component for use in instrumentation tests.](/testing/android/docs/components_for_testing.md)