blob: 4f47cd1b025ed989bd7a104d95057faf398e7c30 [file] [log] [blame] [view]
jbudorick5a9b37f52016-08-17 00:36:431# Android Instrumentation Tests
2
Andrew Grievea971215f2023-12-12 19:22:493Instrumentation tests are JUnit 4 tests that run on devices or emulators. They
4can be either unit tests or integration test.
jbudorick5a9b37f52016-08-17 00:36:435
6[TOC]
7
Henrique Nakashima97546002025-03-26 18:15:468## Unit vs Integration Tests
9
10**When the code under test is library-like code**, mainly defined by its
11contract, intended to be used in many contexts, internally complex, and related
12bugs are more likely to be introduced to the logic inside it than due to
13interactions with other code, **write unit tests**. Unit tests are mostly
14Robolectric (`junit` build targets), but some are Instrumentation tests
15(`unit_device_javatests` build targets).
16
17**When the code under test is application-like code**, mainly defined by its
18behavior, intended to be used in a small number of contexts (often only one),
19internally simple, and related bugs are more likely to be in how/when it is
20called or due to interactions with other code rather its internal business
21logic, **write integration tests**. Integration tests are all Instrumentation
22tests (`javatests` build targets).
23
24## Robolectric (workstation) vs Instrumentation (on-device) Tests
25
26When a unit test doesn't require rendering or interacting with the native
27library, Robolectric tests, which run on workstations, are preferable to
28instrumentation tests, which run on devices and emulators. Robolectric tests are
29faster to compile and run.
30
31See [android_robolectric_tests.md] for more info on Robolectric tests.
32
33For integration app-like tests, use an Instrumentation test.
34
35Where supported, use the existing [Transit
36Layer](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/android/javatests/src/org/chromium/chrome/test/transit)
37to navigate through the app.
38
39Where not supported yet, expand the Transit Layer by defining the expected app
40behavior. See the
41[Public Transit README.md](/base/test/android/javatests/src/org/chromium/base/test/transit/README.md)
42and follow examples in the Transit Layer.
43
44## Examples of Instrumentation Tests
45
46* Instrumentation Integration test example:
47 [ExampleFreshCtaTest](/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleFreshCtaTest.java)
48* Instrumentation Unit test example:
49 [ExampleOnDeviceUnitTest](/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleOnDeviceUnitTest.java)
50
Andrew Grievea971215f2023-12-12 19:22:4951## Tracing
jbudorick5a9b37f52016-08-17 00:36:4352
Nick Wardc650fdf2017-08-12 01:13:4253Enabling tracing during a test run allows all the function calls involved to be
54observed in a visual display (using Chrome's built-in chrome://tracing feature).
55To run a test with tracing, add the `--trace-output` flag to the command used to
56call the instrumentation test (either running the test_runner.py script, or a
Henrique Nakashima97546002025-03-26 18:15:4657generated binary such as `run_chrome_public_test_apk`). The `--trace-output`
58flag takes a filename, which, after the test run, will contain a JSON file
59readable by chrome://tracing.
jbudorick5a9b37f52016-08-17 00:36:4360
Nick Wardc650fdf2017-08-12 01:13:4261By default, the trace includes only certain function calls important to the test
62run, both within the Python test runner framework and the Java code running on
63the device. For a more detailed look, add the (no-argument) `--trace-all` flag.
64This causes every function called on the Python side to be added to the trace.
jbudorick5a9b37f52016-08-17 00:36:4365
Andrew Grievea971215f2023-12-12 19:22:4966## Test Batching Annotations
Michael Thiessen6bafbf02020-05-25 20:49:3567
Henrique Nakashima97546002025-03-26 18:15:4668In Robolectric, all tests are effectively batched.
69
70For Instrumentation tests, see [batching_instrumentation_tests.md] or the summary below:
71
72The
73[`@Batch`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java)
Michael Thiessen6bafbf02020-05-25 20:49:3574annotation is used to run all tests with the same batch group name in the same
Henrique Nakashima97546002025-03-26 18:15:4675instrumentation invocation. In other words, the browser process is not restarted
76between these tests, and so most changes to global state, like launching an
77Activity, may persist between tests within a batch group. The benefit of this is
78that these tests run significantly faster - the per-test cost of restarting the
79process can be as high as 10 seconds (usually around 2 seconds), and that
80doesn't count the cost of starting an Activity like ChromeTabbedActivity.
Michael Thiessen6bafbf02020-05-25 20:49:3581
Andrew Grievea971215f2023-12-12 19:22:4982## Size Annotations
jbudorick5a9b37f52016-08-17 00:36:4383
Andrew Grievea971215f2023-12-12 19:22:4984Size annotations are [used by the test runner] to determine the length of time
Henrique Nakashima97546002025-03-26 18:15:4685to wait before considering a test hung (i.e., its timeout duration), however the
86limits aren't very different currently because all tests get a 60s timeout
87added.
jbudorick5a9b37f52016-08-17 00:36:4388
Andrew Grievea971215f2023-12-12 19:22:4989Annotations from `androidx.test.filters`:
jbudorick5a9b37f52016-08-17 00:36:4390
Henrique Nakashima97546002025-03-26 18:15:4691 - [`@SmallTest`](https://developer.android.com/reference/androidx/test/filters/SmallTest.html) (timeout: **10 (+60) seconds**)
92 - [`@MediumTest`](https://developer.android.com/reference/androidx/test/filters/MediumTest.html) (timeout: **30 (+60) seconds**)
93 - [`@LargeTest`](https://developer.android.com/reference/androidx/test/filters/LargeTest.html) (timeout: **2 (+1) minutes**)
jbudorick5a9b37f52016-08-17 00:36:4394
Andrew Grievea971215f2023-12-12 19:22:4995Annotations from `//base`:
jbudorick5a9b37f52016-08-17 00:36:4396
John Palmera8515fca2021-05-20 03:35:3297 - [`@EnormousTest`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java)
Henrique Nakashima97546002025-03-26 18:15:4698(timeout: **5 (+1) minutes**) Typically used for tests that require WiFi.
John Palmera8515fca2021-05-20 03:35:3299 - [`@IntegrationTest`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java)
Henrique Nakashima97546002025-03-26 18:15:46100(timeout: **10 (+1) minutes**) Used for tests that run against real services.
John Palmera8515fca2021-05-20 03:35:32101 - [`@Manual`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java)
jbudorick5a9b37f52016-08-17 00:36:43102(timeout: **10 hours**) Used for manual tests.
103
Andrew Grievea971215f2023-12-12 19:22:49104[used by the test runner]: https://source.chromium.org/search?q=file:local_device_instrumentation_test_run.py%20symbol:TIMEOUT_ANNOTATIONS&sq=&ss=chromium
jbudorick5a9b37f52016-08-17 00:36:43105
Andrew Grievea971215f2023-12-12 19:22:49106## Annotations that Disable Tests
jbudorick5a9b37f52016-08-17 00:36:43107
108There are several annotations that control whether or not a test runs.
109Some are conditional, others are not.
110
Andrew Grievea971215f2023-12-12 19:22:49111### Unconditional Disabling
jbudorick5a9b37f52016-08-17 00:36:43112
John Palmera8515fca2021-05-20 03:35:32113[**@DisabledTest**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java)
jbudoricka2d64d12016-08-22 22:10:00114unconditionally disables a test.
115```java
116@DisabledTest(
117 // Describes why the test is disabled. Typically includes a crbug link.
118 message = ""
119)
120```
jbudorick5a9b37f52016-08-17 00:36:43121
Andrew Grievea971215f2023-12-12 19:22:49122### Conditional Disabling
jbudorick5a9b37f52016-08-17 00:36:43123
124There are two primary annotation categories that conditionally disable tests:
125**@DisableIf** and **@Restriction**. The **@DisableIf** annotations are intended
126to temporarily disable a test in certain scenarios where it *should* work but
127doesn't. In contrast, the **@Restriction** annotation is intended to
128permanently limit a test to specific configurations. It signifies that the test
129was not, is not, and will not be intended to run beyond those configurations.
130In both cases, conditional disabling manifests as a skipped test.
131
John Palmera8515fca2021-05-20 03:35:32132[**@DisableIf.Build**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#25)
jbudoricka2d64d12016-08-22 22:10:00133allows for conditional test disabling based on values in
jbudorick5a9b37f52016-08-17 00:36:43134[`android.os.Build`](https://developer.android.com/reference/android/os/Build.html):
135
136```java
137@DisableIf.Build(
138
139 // Describes why the test is disabled.
140 message = "",
141
142 // Disables the test on SDK levels that match the given conditions.
143 // Checks against Build.VERSION.SDK_INT.
144 sdk_is_greater_than = 0,
145 sdk_is_less_than = Integer.MAX_VALUE,
146
147 // Disables the test on devices that support the given ABI
148 // (e.g. "arm64-v8a"). Checks against:
149 // - Build.SUPPORTED_ABIS on L+
150 // - Build.CPU_ABI and Build.CPU_ABI2 otherwise
151 supported_abis_includes = "",
152
153 // Disables the test on devices with hardware that matches the given
154 // value. Checks against Build.HARDWARE.
155 hardware_is = "",
156
157 // Disables the test on devices with product names that contain the
158 // given value. Checks against Build.PRODUCT.
159 product_name_includes = "",
160
161)
162```
163
John Palmera8515fca2021-05-20 03:35:32164[**@DisableIf.Device**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#40)
jbudoricka2d64d12016-08-22 22:10:00165allows for conditional test disabling based on whether
jbudorick5a9b37f52016-08-17 00:36:43166a device is a phone, a tablet, or a "large tablet" as determined by
John Palmera8515fca2021-05-20 03:35:32167[org.chromium.ui.base.DeviceFormFactor](https://chromium.googlesource.com/chromium/src/+/main/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java).
Shenghua Zhangcac866d2017-08-29 01:30:55168This is available to tests in
John Palmera8515fca2021-05-20 03:35:32169[//ui](https://chromium.googlesource.com/chromium/src/+/main/ui/)
Shenghua Zhangcac866d2017-08-29 01:30:55170or code that uses //ui.
jbudorick5a9b37f52016-08-17 00:36:43171
172```java
173@DisableIf.Device(
174 // Disables the test on devices that match the given type(s) as described
175 // above.
176 type = {}
177)
178```
179
John Palmera8515fca2021-05-20 03:35:32180[**@Restriction**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java)
jbudoricka2d64d12016-08-22 22:10:00181currently allows for conditional test disabling based on device
jbudorick5a9b37f52016-08-17 00:36:43182type, device performance, internet connectivity, whether Google Play Services is
183up to date, and whether the build was an official one.
184
185```java
186@Restriction(
187 // Possible values include:
188 //
Michael Thiessen6bafbf02020-05-25 20:49:35189 // base:
jbudorick5a9b37f52016-08-17 00:36:43190 // - Restriction.RESTRICTION_TYPE_LOW_END_DEVICE
191 // Restricts the test to low-end devices as determined by SysUtils.isLowEndDevice().
192 //
193 // - Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE
194 // Restricts the test to non-low-end devices as determined by SysUtils.isLowEndDevice().
195 //
196 // - Restriction.RESTRICTION_TYPE_INTERNET
197 // Restricts the test to devices that have an internet connection.
198 //
199 // chrome:
200 // - ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES
201 // Restricts the test to devices with up-to-date versions of Google Play Services.
202 //
jbudorick5a9b37f52016-08-17 00:36:43203 // - ChromeRestriction.RESTRICTION_TYPE_OFFICIAL_BUILD
204 // Restricts the test to official builds as determined by ChromeVersionInfo.isOfficialBuild().
Shenghua Zhangcac866d2017-08-29 01:30:55205 //
206 // ui:
207 // - UiRestriction.RESTRICTION_TYPE_PHONE
208 // Restricts the test to phones as determined by DeviceFormFactor.
209 //
210 // - UiRestriction.RESTRICTION_TYPE_TABLET
211 // Restricts the test to tablets as determined by DeviceFormFactor.
jbudorick5a9b37f52016-08-17 00:36:43212 value = {}
213)
214```
215
John Palmera8515fca2021-05-20 03:35:32216[**@MinAndroidSdkLevel**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java)
jbudoricka2d64d12016-08-22 22:10:00217is similar to **@Restriction** in purpose in that it's
jbudorick5a9b37f52016-08-17 00:36:43218intended to permanently limit a test to only recent versions of Android.
219
220```java
221@MinAndroidSdkLevel(
222 // The minimum SDK level at which this test should be executed. Checks
223 // against Build.VERSION.SDK_INT.
224 value = 0
225)
226```
227
Andrew Grievea971215f2023-12-12 19:22:49228## Command-Line Flags Annotations
jbudorick5a9b37f52016-08-17 00:36:43229
230Several annotations affect how a test is run in interesting or nontrivial ways.
231
John Palmera8515fca2021-05-20 03:35:32232[**@CommandLineFlags.Add**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#46)
jbudoricka2d64d12016-08-22 22:10:00233and
John Palmera8515fca2021-05-20 03:35:32234[**@CommandLineFlags.Remove**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#58)
jbudoricka2d64d12016-08-22 22:10:00235manipulate Chrome's
jbudorick5a9b37f52016-08-17 00:36:43236command-line flags on a per-test basis (i.e., the flags handled by
John Palmera8515fca2021-05-20 03:35:32237[`org.chromium.base.CommandLine`](https://chromium.googlesource.com/chromium/src/+/main/base/android/java/src/org/chromium/base/CommandLine.java) and
238[`base::CommandLine`](https://chromium.googlesource.com/chromium/src/+/main/base/command_line.h)).
jbudorick5a9b37f52016-08-17 00:36:43239
240```java
241@CommandLineFlags.Add(
242 // The flags to add to the command line for this test. These can be
243 // anything and typically should include the leading dashes (e.g. "--foo").
244 value = {}
245)
246
247@CommandLineFlags.Remove(
248 // The flags to remove from the command line for this test. These can only
249 // be flags added via @CommandLineFlags.Add. Flags already present in the
250 // command-line file on the device are only present in the native
251 // CommandLine object and cannot be manipulated.
252 value = {}
253)
254```
255
Andrew Grievea971215f2023-12-12 19:22:49256## Feature Annotations
jbudorick5a9b37f52016-08-17 00:36:43257
John Palmera8515fca2021-05-20 03:35:32258[**@Feature**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java)
jbudoricka2d64d12016-08-22 22:10:00259has been used inconsistently in Chromium to group tests across
jbudorick5a9b37f52016-08-17 00:36:43260test cases according to the feature they're testing.
261
262```java
263@Feature(
264 // The features associated with this test. These can be anything.
265 value = {}
266)
267```
268
269@Feature doesn't have an inherent function, but it can be used to filter tests
270via the test runner's
Andrew Grieveb5b3bb32023-10-04 13:55:51271`-A/--annotation` and `-E/--exclude-annotation` flags. For example, this would
272run only the tests with @Feature annotations containing at least "Sync" in
273`chrome_public_test_apk`:
jbudorick5a9b37f52016-08-17 00:36:43274
275```bash
276out/Debug/bin/run_chrome_public_test_apk -A Feature=Sync
277```