Si eres nuevo en Bazel, comienza con el instructivo Cómo compilar Android con Bazel.

Figura 1: Ejecuta pruebas de instrumentación de Android paralelas.
android_instrumentation_test
permite que los desarrolladores prueben sus apps en emuladores y dispositivos Android.
Utiliza APIs reales del framework de Android y la biblioteca de pruebas de Android.
Para la hermeticidad y la reproducibilidad, Bazel crea y lanza emuladores de Android en un entorno de pruebas, lo que garantiza que las pruebas siempre se ejecuten desde un estado limpio. Cada prueba obtiene una instancia de emulador aislada, lo que permite que las pruebas se ejecuten en paralelo sin pasar estados entre ellas.
Para obtener más información sobre las pruebas de instrumentación de Android, consulta la documentación para desarrolladores de Android.
Informa los problemas en la herramienta de seguimiento de errores de GitHub.
Cómo funciona
Cuando ejecutas bazel test en un destino android_instrumentation_test por
primera vez, Bazel realiza los siguientes pasos:
- Compila el APK de prueba, el APK en prueba y sus dependencias transitivas.
- Crea, inicia y almacena en caché estados limpios del emulador.
- Inicia el emulador.
- Instala los APKs.
- Ejecuta pruebas con el Android Test Orchestrator.
- Cierra el emulador.
- Informa los resultados.
En las ejecuciones de prueba posteriores, Bazel inicia el emulador desde el estado limpio y almacenado en caché creado en el paso 2, por lo que no quedan estados de ejecuciones anteriores. El almacenamiento en caché del estado del emulador también acelera las ejecuciones de prueba.
Requisitos previos
Asegúrate de que tu entorno cumpla con los siguientes requisitos previos:
Linux. Se probó en Ubuntu 16.04 y 18.04.
Bazel 0.12.0 o posterior. Para verificar la versión, ejecuta
bazel info release.
bazel info releaseEsto genera un resultado similar al siguiente:
release 4.1.0
- KVM. Bazel requiere que los emuladores tengan aceleración de hardware con KVM en Linux. Puedes seguir estas instrucciones de instalación para Ubuntu.
Para verificar que KVM tenga la configuración correcta, ejecuta lo siguiente:
apt-get install cpu-checker && kvm-okSi se imprime el siguiente mensaje, tienes la configuración correcta:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. Para ejecutar pruebas sin interfaz gráfica (por ejemplo, en servidores de CI), Bazel requiere el búfer de fotogramas virtual X.
Para instalarlo, ejecuta lo siguiente:
apt-get install xvfbPara verificar que Xvfb esté instalado correctamente y que se encuentre en /usr/bin/Xvfb
ejecuta lo siguiente:
which XvfbEsta es la salida:
/usr/bin/Xvfb
- Bibliotecas de 32 bits. Algunos de los objetos binarios que usa la infraestructura de prueba son de 32 bits, por lo que, en máquinas de 64 bits, asegúrate de que se puedan ejecutar objetos binarios de 32 bits. Para Ubuntu, instala estas bibliotecas de 32 bits:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386Cómo comenzar
Este es un gráfico de dependencias de destino típico de un android_instrumentation_test:

Figura 2: Gráfico de dependencias de destino de un android_instrumentation_test.
Archivo BUILD
El gráfico se traduce en un archivo BUILD como este:
android_instrumentation_test(
name = "my_test",
test_app = ":my_test_app",
target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86",
)
# Test app and library
android_binary(
name = "my_test_app",
instruments = ":my_app",
manifest = "AndroidTestManifest.xml",
deps = [":my_test_lib"],
# ...
)
android_library(
name = "my_test_lib",
srcs = glob(["javatest/**/*.java"]),
deps = [
":my_app_lib",
"@maven//:androidx_test_core",
"@maven//:androidx_test_runner",
"@maven//:androidx_test_espresso_espresso_core",
],
# ...
)
# Target app and library under test
android_binary(
name = "my_app",
manifest = "AndroidManifest.xml",
deps = [":my_app_lib"],
# ...
)
android_library(
name = "my_app_lib",
srcs = glob(["java/**/*.java"]),
deps = [
"@maven//:androidx_appcompat_appcompat",
"@maven//:androidx_annotation_annotation",
]
# ...
)
Los atributos principales de la regla android_instrumentation_test son los siguientes:
test_app: Es un destinoandroid_binary. Este destino contiene código de prueba y dependencias como Espresso y UIAutomator. El destinoandroid_binaryseleccionado es necesario para especificar un atributoinstrumentsque apunte a otroandroid_binary, que es la app que está a prueba.target_device: Es un destinoandroid_device. Este destino describe las especificaciones del emulador de Android que Bazel usa para crear, iniciar y ejecutar las pruebas. Consulta la sección sobre cómo elegir un dispositivo Android para obtener más información.
El AndroidManifest.xml de la app de prueba debe incluir una <instrumentation>
etiqueta.
Esta etiqueta debe especificar los atributos del paquete de la app de destino y
el nombre de clase completamente calificado del ejecutor de pruebas de instrumentación,
androidx.test.runner.AndroidJUnitRunner.
Este es un ejemplo AndroidTestManifest.xml para la app de prueba:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.app.test"
android:versionCode="1"
android:versionName="1.0">
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.example.android.app" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="27" />
<application >
<!-- ... -->
</application>
</manifest>
Dependencias de WORKSPACE
Para usar esta regla, tu proyecto debe depender de estos repositorios externos:
@androidsdk: Es el SDK de Android. Descárgalo a través de Android Studio.@android_test_support: Aloja el ejecutor de pruebas, el iniciador del emulador y los destinosandroid_device. Puedes encontrar la versión más reciente aquí.
Para habilitar estas dependencias, agrega las siguientes líneas a tu WORKSPACE
archivo:
# Android SDK
android_sdk_repository(
name = "androidsdk",
path = "/path/to/sdk", # or set ANDROID_HOME
)
# Android Test Support
ATS_COMMIT = "$COMMIT_HASH"
http_archive(
name = "android_test_support",
strip_prefix = "android-test-%s" % ATS_COMMIT,
urls = ["https://github.com/android/android-test/archive/%s.tar.gz" % ATS_COMMIT],
)
load("@android_test_support//:repo.bzl", "android_test_repositories")
android_test_repositories()
Dependencias de Maven
Para administrar dependencias en artefactos de Maven de repositorios, como Google
Maven o Maven Central,
debes usar un solucionador de Maven, como
rules_jvm_external.
En el resto de esta página, se muestra cómo usar rules_jvm_external para
resolver y recuperar dependencias de repositorios de Maven.
Cómo elegir un destino android_device
android_instrumentation_test.target_device especifica en qué dispositivo Android se deben
ejecutar las pruebas. Estos destinos android_device se definen en
@android_test_support.
Por ejemplo, puedes consultar las fuentes de un destino en particular ejecutando lo siguiente:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86Esto genera un resultado similar al siguiente:
# .../external/android_test_support/tools/android/emulated_devices/generic_phone/BUILD:43:1
android_device(
name = "android_23_x86",
visibility = ["//visibility:public"],
tags = ["requires-kvm"],
generator_name = "generic_phone",
generator_function = "make_device",
generator_location = "tools/android/emulated_devices/generic_phone/BUILD:43",
vertical_resolution = 800,
horizontal_resolution = 480,
ram = 2048,
screen_density = 240,
cache = 32,
vm_heap = 256,
system_image = "@android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86_images",
default_properties = "@android_test_support//tools/android/emulated_devices/generic_phone:_android_23_x86_props",
)
Los nombres de destino del dispositivo usan esta plantilla:
@android_test_support//tools/android/emulated_devices/device_type:system_api_level_x86_qemu2
Para iniciar un android_device, se requiere la system_image para el nivel de API
seleccionado. Para descargar la imagen del sistema, usa el SDK de Android
tools/bin/sdkmanager. Por ejemplo, para descargar la imagen del sistema para
generic_phone:android_23_x86, ejecuta $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86".
Para ver la lista completa de destinos android_device admitidos en
@android_test_support, ejecuta el siguiente comando:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'Actualmente, Bazel solo admite emuladores basados en x86. Para obtener un mejor rendimiento, usa
QEMU2 android_device destinos en lugar de QEMU.
Cómo ejecutar pruebas
Para ejecutar pruebas, agrega estas líneas al archivo
project root:/.bazelrc de tu proyecto.
# Configurations for testing with Bazel
# Select a configuration by running
# `bazel test //my:target --config={headless, gui, local_device}`
# Headless instrumentation tests (No GUI)
test:headless --test_arg=--enable_display=false
# Graphical instrumentation tests. Ensure that $DISPLAY is set.
test:gui --test_env=DISPLAY
test:gui --test_arg=--enable_display=true
# Testing with a local emulator or device. Ensure that `adb devices` lists the
# device.
# Run tests serially.
test:local_device --test_strategy=exclusive
# Use the local device broker type, as opposed to WRAPPED_EMULATOR.
test:local_device --test_arg=--device_broker_type=LOCAL_ADB_SERVER
# Uncomment and set $device_id if there is more than one connected device.
# test:local_device --test_arg=--device_serial_number=$device_id
Luego, usa una de las configuraciones para ejecutar pruebas:
bazel test //my/test:target --config=guibazel test //my/test:target --config=headlessbazel test //my/test:target --config=local_device
Usa solo una configuración o las pruebas fallarán.
Pruebas sin interfaz gráfica
Con Xvfb, es posible realizar pruebas con emuladores sin la interfaz gráfica, también conocidas como pruebas sin interfaz gráfica. Para inhabilitar la interfaz gráfica
cuando se ejecutan pruebas, pasa el argumento de prueba --enable_display=false a Bazel:
bazel test //my/test:target --test_arg=--enable_display=falsePruebas de GUI
Si se configura la variable de entorno $DISPLAY, es posible habilitar la
interfaz gráfica del emulador mientras se ejecuta la prueba. Para ello, pasa
estos argumentos de prueba a Bazel:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAYPruebas con un emulador o dispositivo local
Bazel también admite pruebas directamente en un emulador iniciado de forma local o en un dispositivo conectado. Pasa las marcas
--test_strategy=exclusive y
--test_arg=--device_broker_type=LOCAL_ADB_SERVER para habilitar el modo de prueba local.
Si hay más de un dispositivo conectado, pasa la marca
--test_arg=--device_serial_number=$device_id donde $device_id es el ID de
el dispositivo o emulador que aparece en adb devices.
Proyectos de muestra
Si buscas muestras de proyectos canónicos, consulta las muestras de pruebas de Android para proyectos que usan Espresso y UIAutomator.
Configuración de Espresso
Si escribes pruebas de IU con Espresso
(androidx.test.espresso), puedes usar los siguientes fragmentos para configurar tu
espacio de trabajo de Bazel con la lista de artefactos de Espresso de uso común y sus
dependencias:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
Una forma de organizar estas dependencias es crear una biblioteca compartida //:test_deps en tu archivo project root/BUILD.bazel:
java_library(
name = "test_deps",
visibility = ["//visibility:public"],
exports = [
"@maven//:androidx_test_espresso_espresso_core",
"@maven//:androidx_test_rules",
"@maven//:androidx_test_runner",
"@maven//:javax_inject_javax_inject"
"@maven//:org_hamcrest_java_hamcrest",
"@maven//:junit_junit",
],
)
Luego, agrega las dependencias requeridas en project root/WORKSPACE:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
RULES_JVM_EXTERNAL_TAG = "2.8"
RULES_JVM_EXTERNAL_SHA = "79c9850690d7614ecdb72d68394f994fef7534b292c4867ce5e7dec0aa7bdfad"
http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)
load("@rules_jvm_external//:defs.bzl", "maven_install")
maven_install(
artifacts = [
"junit:junit:4.12",
"javax.inject:javax.inject:1",
"org.hamcrest:java-hamcrest:2.0.0.0"
"androidx.test.espresso:espresso-core:3.1.1",
"androidx.test:rules:aar:1.1.1",
"androidx.test:runner:aar:1.1.1",
],
repositories = [
"https://maven.google.com",
"https://repo1.maven.org/maven2",
],
)
Por último, en tu destino android_binary de prueba, agrega la //:test_deps
dependencia:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
Sugerencias
Cómo leer registros de prueba
Usa --test_output=errors para imprimir registros de pruebas con errores o
--test_output=all para imprimir todos los resultados de las pruebas. Si buscas un
registro de prueba individual, ve a
$PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName.
Por ejemplo, los registros de prueba del proyecto canónico BasicSample se encuentran en
bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest. Para acceder a ellos, ejecuta lo siguiente:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTestEsto genera el siguiente resultado:
$ tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
.
├── adb.409923.log
├── broker_logs
│ ├── aapt_binary.10.ok.txt
│ ├── aapt_binary.11.ok.txt
│ ├── adb.12.ok.txt
│ ├── adb.13.ok.txt
│ ├── adb.14.ok.txt
│ ├── adb.15.fail.txt
│ ├── adb.16.ok.txt
│ ├── adb.17.fail.txt
│ ├── adb.18.ok.txt
│ ├── adb.19.fail.txt
│ ├── adb.20.ok.txt
│ ├── adb.21.ok.txt
│ ├── adb.22.ok.txt
│ ├── adb.23.ok.txt
│ ├── adb.24.fail.txt
│ ├── adb.25.ok.txt
│ ├── adb.26.fail.txt
│ ├── adb.27.ok.txt
│ ├── adb.28.fail.txt
│ ├── adb.29.ok.txt
│ ├── adb.2.ok.txt
│ ├── adb.30.ok.txt
│ ├── adb.3.ok.txt
│ ├── adb.4.ok.txt
│ ├── adb.5.ok.txt
│ ├── adb.6.ok.txt
│ ├── adb.7.ok.txt
│ ├── adb.8.ok.txt
│ ├── adb.9.ok.txt
│ ├── android_23_x86.1.ok.txt
│ └── exec-1
│ ├── adb-2.txt
│ ├── emulator-2.txt
│ └── mksdcard-1.txt
├── device_logcat
│ └── logcat1635880625641751077.txt
├── emulator_itCqtc.log
├── outputs.zip
├── pipe.log.txt
├── telnet_pipe.log.txt
└── tmpuRh4cy
├── watchdog.err
└── watchdog.out
4 directories, 41 files
Cómo leer registros del emulador
Los registros del emulador para destinos android_device se almacenan en el /tmp/
directorio con el nombre emulator_xxxxx.log, donde xxxxx es una
secuencia de caracteres generada de forma aleatoria.
Usa este comando para encontrar el registro del emulador más reciente:
ls -1t /tmp/emulator_*.log | head -n 1Pruebas en varios niveles de API
Si deseas realizar pruebas en varios niveles de API, puedes usar una comprensión de lista para crear destinos de prueba para cada nivel de API. Por ejemplo:
API_LEVELS = [
"19",
"20",
"21",
"22",
]
[android_instrumentation_test(
name = "my_test_%s" % API_LEVEL,
test_app = ":my_test_app",
target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_%s_x86_qemu2" % API_LEVEL,
) for API_LEVEL in API_LEVELS]
Problemas conocidos
- Los procesos del servidor de ADB bifurcados no finalizan después de las pruebas
- Si bien la compilación de APK funciona en todas las plataformas (Linux, macOS y Windows), las pruebas solo funcionan en Linux.
- Incluso con
--config=local_adb, los usuarios aún deben especificarandroid_instrumentation_test.target_device. - Si se usa un dispositivo o emulador local, Bazel no desinstala los APKs después de la prueba. Para limpiar los paquetes, ejecuta este comando:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall