Si es la primera vez que usas Bazel, comienza con el lab Cómo compilar Android con Instructivo de Bazel.
Figura 1: Cómo ejecutar pruebas de instrumentación de Android paralelas
android_instrumentation_test
les permite a los desarrolladores probar sus apps en dispositivos y emuladores de Android.
Utiliza APIs reales del framework de Android y la biblioteca de pruebas de Android.
Para hermeticidad y reproducibilidad, Bazel crea y lanza Android. emuladores en una zona de pruebas, lo que garantiza que las pruebas siempre se ejecuten en un estado limpio. Cada La prueba obtiene una instancia aislada del emulador, 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 el vínculo Android desarrollador documentación.
Informa los problemas en la Herramienta de seguimiento de errores de GitHub.
Cómo funciona
Cuando ejecutas bazel test
en un objetivo android_instrumentation_test
para el
primera vez, Bazel realiza los siguientes pasos:
- Compila el APK de prueba, el APK que se está probando y sus dependencias transitivas
- Crea, inicia y almacena en caché estados limpios del emulador
- Inicia el emulador.
- Instala los APK
- Ejecuta pruebas con Android Test Orchestrator.
- Apaga 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 restantes de las ejecuciones anteriores. Almacenamiento en caché el 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 una versión posterior Ejecuta
bazel info release
para verificar la versión.
bazel info release
Esto da como resultado un resultado similar al siguiente:
release 4.1.0
- KVM Bazel requiere que los emuladores cuenten con hardware. aceleración con KVM en Linux. Puedes seguir estos instrucciones de instalación para Ubuntu.
Para verificar que KVM tenga la configuración correcta, ejecuta el siguiente comando:
apt-get install cpu-checker && kvm-ok
Si 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 instalarla, ejecuta el siguiente comando:
apt-get install xvfb
Verifica que Xvfb
esté instalado correctamente y que esté instalado en /usr/bin/Xvfb
.
ejecutando lo siguiente:
which Xvfb
Esta es la salida:
/usr/bin/Xvfb
- Bibliotecas de 32 bits Algunos de los objetos binarios que usa la infraestructura de prueba son 32 bits, es decir, en máquinas de 64 bits, asegúrate de que se puedan ejecutar los de 32 bits. Para En Ubuntu, instala estas bibliotecas de 32 bits:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
Cómo comenzar
A continuación, se muestra un gráfico de dependencia de destino típico de un android_instrumentation_test
:
Figura 2: Gráfico de la dependencia de destino de un android_instrumentation_test
Archivo BUILD
El gráfico se traduce en un archivo BUILD
de la siguiente manera:
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 objetivoandroid_binary
. Este destino contiene código de prueba y dependencias, como Espresso y UIAutomator. Elandroid_binary
seleccionado el destino debe especificar un atributoinstruments
que apunte a otroandroid_binary
, que es la app que se está probandotarget_device
: Es un objetivoandroid_device
. Este objetivo describe la especificaciones del emulador de Android que Bazel usa para crear, iniciar y ejecuta las pruebas. Consulta la sección sobre cómo elegir un dispositivo Android dispositivo para obtener más información.
El AndroidManifest.xml
de la app de prueba debe incluir un <instrumentation>
etiqueta.
Esta etiqueta debe especificar los atributos para el 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 AndroidTestManifest.xml
de ejemplo 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 estas reglas repositorios:
@androidsdk
: El SDK de Android. Descárgala a través de Android Studio.@android_test_support
: Aloja el ejecutor de pruebas, el selector del emulador yandroid_device
objetivos. 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 Maven desde repositorios, como Google
Maven o Maven Central,
deberías usar un agente de resolución de Maven, como
rules_jvm_external
En el resto de esta página, se muestra cómo usar rules_jvm_external
para lo siguiente:
resolver y recuperar dependencias de repositorios de Maven.
Cómo elegir un destino android_device
android_instrumentation_test.target_device
especifica a qué dispositivo Android
ejecutaste las pruebas. Estos android_device
objetivos se definen en
@android_test_support
Por ejemplo, puedes ejecutar lo siguiente para consultar las fuentes de un destino en particular:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86
Esto da como resultado 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
, el system_image
de la API seleccionada
el nivel de acceso es obligatorio. Para descargar la imagen del sistema, usa el SDK de Android
tools/bin/sdkmanager
Por ejemplo, para descargar la imagen del sistema de
generic_phone:android_23_x86
, ejecuta $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86"
.
Para ver la lista completa de destinos admitidos de android_device
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, utiliza
QEMU2
objetivos android_device
en lugar de QEMU
.
Cómo ejecutar pruebas
Para ejecutar pruebas, agrega estas líneas al directorio
project root:/.bazelrc
.
# 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=gui
bazel test //my/test:target --config=headless
bazel 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
de la API de SQL, también conocida como
pruebas sin interfaz gráfica. Para inhabilitar la interfaz gráfica
Cuando ejecutes pruebas, pasa el argumento de prueba --enable_display=false
a Bazel:
bazel test //my/test:target --test_arg=--enable_display=false
Pruebas de la GUI
Si se establece la variable de entorno $DISPLAY
, es posible habilitar
Interfaz gráfica del emulador mientras se ejecuta la prueba. Para hacer esto, pasa
estos argumentos de prueba para Bazel:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAY
Cómo realizar pruebas con un emulador o dispositivo local
Bazel también admite pruebas directamente en un emulador iniciado de forma local o conectado
dispositivo. Pasa las banderas
--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, pasar la bandera.
--test_arg=--device_serial_number=$device_id
, en el que $device_id
es el ID de
el dispositivo o emulador que se indica en adb devices
Proyectos de muestra
Si buscas muestras de proyectos canónicos, consulta el artículo Pruebas de Android muestras para proyectos que usan Espresso y UIAutomator.
Configuración de Espresso
Si escribes pruebas de IU con Espresso
(androidx.test.espresso
), puedes utilizar los siguientes fragmentos para configurar tu
Espacio de trabajo de Bazel con la lista de artefactos de Espresso de uso frecuente 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 un //:test_deps
compartido
biblioteca en el 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 necesarias 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 objetivo android_binary
de prueba, agrega //: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 las pruebas fallidas.
--test_output=all
para imprimir todos los resultados de la prueba. Si estás buscando un
registro de pruebas 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
, ejecuta lo siguiente:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
Esto da como resultado 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 los destinos android_device
se almacenan en /tmp/
con el nombre emulator_xxxxx.log
, donde xxxxx
es un
de caracteres generada al azar.
Usa este comando para encontrar el registro más reciente del emulador:
ls -1t /tmp/emulator_*.log | head -n 1
Pruebas con varios niveles de API
Si deseas realizar pruebas con varios niveles de API, puedes usar una lista de comprensión básica para crear objetivos 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 adb bifurcado no se finalizan pruebas
- Si bien la compilación de APK funciona en todas las plataformas (Linux, macOS y Windows), las pruebas solo funciona en Linux.
- Incluso con
--config=local_adb
, los usuarios deben especificar.android_instrumentation_test.target_device
- Si usas un dispositivo local o emulador, Bazel no desinstala los APK después la prueba. Ejecuta este comando para limpiar los paquetes:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall