Figure 1. Running parallel Android instrumentation tests.
android_instrumentation_test
allows developers to test their apps on Android emulators and devices.
It utilizes real Android framework APIs and the Android Test Library.
For hermeticity and reproducibility, Bazel creates and launches Android
emulators in a sandbox, ensuring that tests always run from a clean state. Each
test gets an isolated emulator instance, allowing tests to run in parallel
without passing states between them.
For more information on Android instrumentation tests, check out the Android
developer
documentation.
Please file issues in the GitHub issue tracker.
How it works
When you runbazel test on an android_instrumentation_test target for the
first time, Bazel performs the following steps:
- Builds the test APK, APK under test, and their transitive dependencies
- Creates, boots, and caches clean emulator states
- Starts the emulator
- Installs the APKs
- Runs tests utilizing the Android Test Orchestrator
- Shuts down the emulator
- Reports the results
Prerequisites
Ensure your environment satisfies the following prerequisites:- Linux. Tested on Ubuntu 16.04, and 18.04.
-
Bazel 0.12.0 or later. Verify the version by running
bazel info release.
- KVM. Bazel requires emulators to have hardware acceleration with KVM on Linux. You can follow these installation instructions for Ubuntu.
- Xvfb. To run headless tests (for example, on CI servers), Bazel requires the X virtual framebuffer.
Xvfb is installed correctly and is installed at /usr/bin/Xvfb
by running:
- 32-bit Libraries. Some of the binaries used by the test infrastructure are 32-bit, so on 64-bit machines, ensure that 32-bit binaries can be run. For Ubuntu, install these 32-bit libraries:
Getting started
Here is a typical target dependency graph of anandroid_instrumentation_test:
Figure 2. Target dependency graph of an android_instrumentation_test.
BUILD file
The graph translates into aBUILD file like this:
android_instrumentation_test are:
-
test_app: Anandroid_binarytarget. This target contains test code and dependencies like Espresso and UIAutomator. The selectedandroid_binarytarget is required to specify aninstrumentsattribute pointing to anotherandroid_binary, which is the app under test. -
target_device: Anandroid_devicetarget. This target describes the specifications of the Android emulator which Bazel uses to create, launch and run the tests. See the section on choosing an Android device for more information.
AndroidManifest.xml must include an <instrumentation>
tag.
This tag must specify the attributes for the package of the target app and
the fully qualified class name of the instrumentation test runner,
androidx.test.runner.AndroidJUnitRunner.
Here is an example AndroidTestManifest.xml for the test app:
WORKSPACE dependencies
In order to use this rule, your project needs to depend on these external repositories:-
@androidsdk: The Android SDK. Download this through Android Studio. -
@android_test_support: Hosts the test runner, emulator launcher, andandroid_devicetargets. You can find the latest release here.
WORKSPACE
file:
Maven dependencies
For managing dependencies on Maven artifacts from repositories, such as Google Maven or Maven Central, you should use a Maven resolver, such asrules_jvm_external.
The rest of this page shows how to use rules_jvm_external to
resolve and fetch dependencies from Maven repositories.
Choosing an android_device target
android_instrumentation_test.target_device specifies which Android device to
run the tests on. These android_device targets are defined in
@android_test_support.
For example, you can query for the sources for a particular target by running:
android_device, the system_image for the selected API
level is required. To download the system image, use Android SDK’s
tools/bin/sdkmanager. For example, to download the system image for
generic_phone:android_23_x86, run $sdk/tools/bin/sdkmanager "system-images;android-23;default;x86".
To see the full list of supported android_device targets in
@android_test_support, run the following command:
QEMU2 android_device targets instead of QEMU ones.
Running tests
To run tests, add these lines to your project’s{{ '<var>' }}project root{{ '</var>' }}:{{ '<var>' }}/.bazelrc file.
bazel test //my/test:target --config=guibazel test //my/test:target --config=headlessbazel test //my/test:target --config=local_device
Headless testing
WithXvfb, it is possible to test with emulators without the graphical
interface, also known as headless testing. To disable the graphical interface
when running tests, pass the test argument --enable_display=false to Bazel:
GUI testing
If the$DISPLAY environment variable is set, it’s possible to enable the
graphical interface of the emulator while the test is running. To do this, pass
these test arguments to Bazel:
Testing with a local emulator or device
Bazel also supports testing directly on a locally launched emulator or connected device. Pass the flags--test_strategy=exclusive and
--test_arg=--device_broker_type=LOCAL_ADB_SERVER to enable local testing mode.
If there is more than one connected device, pass the flag
--test_arg=--device_serial_number=$device_id where $device_id is the id of
the device/emulator listed in adb devices.
Sample projects
If you are looking for canonical project samples, see the Android testing samples for projects using Espresso and UIAutomator.Espresso setup
If you write UI tests with Espresso (androidx.test.espresso), you can use the following snippets to set up your
Bazel workspace with the list of commonly used Espresso artifacts and their
dependencies:
//:test_deps shared
library in your {{ "<var>" }}project root{{ "</var>" }}/BUILD.bazel file:
{{ "<var>" }}project root{{ "</var>" }}/WORKSPACE:
android_binary target, add the //:test_deps
dependency:
Tips
Reading test logs
Use--test_output=errors to print logs for failing tests, or
--test_output=all to print all test output. If you’re looking for an
individual test log, go to
$PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName.
For example, the test logs for BasicSample canonical project are in
bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest, run:
Reading emulator logs
The emulator logs forandroid_device targets are stored in the /tmp/
directory with the name emulator_xxxxx.log, where xxxxx is a
randomly-generated sequence of characters.
Use this command to find the latest emulator log:
Testing against multiple API levels
If you would like to test against multiple API levels, you can use a list comprehension to create test targets for each API level. For example:Known issues
- Forked adb server processes are not terminated after tests
- While APK building works on all platforms (Linux, macOS, Windows), testing only works on Linux.
- Even with
--config=local_adb, users still need to specifyandroid_instrumentation_test.target_device. - If using a local device or emulator, Bazel does not uninstall the APKs after the test. Clean the packages by running this command: