Jika Anda baru mengenal Bazel, mulailah dengan Membangun Android dengan Bazel.
Gambar 1. Menjalankan uji instrumentasi Android paralel.
android_instrumentation_test
memungkinkan developer menguji aplikasi mereka di emulator dan perangkat Android.
Aplikasi ini menggunakan API framework Android asli dan Android Test Library.
Karena sifatnya yang hermetis dan dapat diproduksi ulang, Bazel membuat dan meluncurkan Android emulator di sandbox, yang memastikan bahwa pengujian selalu berjalan dari kondisi bersih. Masing-masing pengujian mendapatkan instance emulator yang terisolasi, sehingga memungkinkan pengujian berjalan secara paralel tanpa meneruskan status di antara keduanya.
Untuk informasi selengkapnya tentang uji instrumentasi Android, lihat artikel pengembang dokumentasi tambahan.
Laporkan masalah di Issue Tracker GitHub.
Cara kerjanya
Saat Anda menjalankan bazel test
pada target android_instrumentation_test
untuk
pertama kali, Bazel melakukan
langkah-langkah berikut:
- Membangun APK pengujian, APK yang sedang diuji, dan dependensi transitifnya
- Membuat, melakukan booting, dan meng-cache status emulator yang bersih
- Memulai emulator
- Menginstal APK
- Menjalankan pengujian menggunakan Android Test Orchestrator
- Mematikan emulator
- Melaporkan hasil
Pada pengujian berikutnya, Bazel mem-booting emulator dari status bersih dan di-cache yang dibuat di langkah 2, sehingga tidak ada status yang tersisa dari proses sebelumnya. Menyimpan ke cache status emulator juga mempercepat pengujian.
Prasyarat
Pastikan lingkungan Anda memenuhi prasyarat berikut:
Linux. Diuji pada Ubuntu 16.04, dan 18.04.
Bazel 0.12.0 atau yang lebih baru. Verifikasi versi dengan menjalankan
bazel info release
.
bazel info release
Hasilnya adalah output yang mirip dengan yang berikut ini:
release 4.1.0
- KVM. Bazel mengharuskan emulator memiliki perangkat keras percepatan dengan KVM di Linux. Anda dapat mengikuti petunjuk penginstalan untuk Ubuntu.
Untuk memverifikasi bahwa KVM memiliki konfigurasi yang benar, jalankan:
apt-get install cpu-checker && kvm-ok
Jika pesan berikut tercetak, Anda memiliki konfigurasi yang benar:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. Untuk menjalankan pengujian headless (misalnya, di server CI), Bazel memerlukan framebuffer virtual X.
Untuk menginstalnya, jalankan:
apt-get install xvfb
Pastikan bahwa Xvfb
sudah diinstal dengan benar dan diinstal di /usr/bin/Xvfb
dengan menjalankan:
which Xvfb
Outputnya adalah sebagai berikut:
/usr/bin/Xvfb
- Library 32-bit. Beberapa biner yang digunakan oleh infrastruktur pengujian adalah 32-bit, jadi pada mesin 64-bit, pastikan bahwa biner 32-bit dapat dijalankan. Sebagai Ubuntu, instal library 32-bit ini:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
Memulai
Berikut adalah grafik dependensi target standar untuk android_instrumentation_test
:
Gambar 2. Grafik dependensi target android_instrumentation_test
.
file BUILD
Grafik ini diterjemahkan ke dalam file BUILD
seperti ini:
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",
]
# ...
)
Atribut utama aturan android_instrumentation_test
adalah:
test_app
: Targetandroid_binary
. Target ini berisi kode uji dan dependensi seperti Espresso dan UIAutomator.android_binary
yang dipilih target diperlukan untuk menentukan atributinstruments
yang mengarah ke elemen lainnyaandroid_binary
, yang merupakan aplikasi yang sedang diuji.target_device
: Targetandroid_device
. Target ini mendeskripsikan spesifikasi emulator Android yang digunakan Bazel untuk membuat, meluncurkan, menjalankan pengujian. Lihat bagian tentang memilih Android perangkat untuk mengetahui informasi selengkapnya.
AndroidManifest.xml
aplikasi pengujian harus menyertakan <instrumentation>
menggunakan tag.
Tag ini harus menentukan atribut untuk paket aplikasi target dan
nama class runner uji instrumentasi yang sepenuhnya memenuhi syarat,
androidx.test.runner.AndroidJUnitRunner
.
Berikut adalah contoh AndroidTestManifest.xml
untuk aplikasi pengujian:
<?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>
Dependensi WORKSPACE
Untuk menggunakan aturan ini, proyek Anda harus bergantung pada repositori:
@androidsdk
: Android SDK. Download melalui Android Studio.@android_test_support
: Menghosting runner pengujian, peluncur emulator, danandroid_device
target. Anda dapat menemukan rilis terbaru di sini.
Aktifkan dependensi ini dengan menambahkan baris berikut ke WORKSPACE
Anda
file:
# 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()
Dependensi Maven
Untuk mengelola dependensi pada artefak Maven dari repositori, seperti Google
Maven atau Maven Central,
Anda sebaiknya menggunakan resolver Maven, seperti
rules_jvm_external
.
Bagian selanjutnya dari halaman ini menunjukkan cara menggunakan rules_jvm_external
untuk
menentukan dan mengambil dependensi dari repositori Maven.
Memilih target android_device
android_instrumentation_test.target_device
menentukan perangkat Android yang akan
untuk menjalankan pengujian. android_device
target ini ditentukan di
@android_test_support
.
Misalnya, Anda dapat membuat kueri untuk sumber target tertentu dengan menjalankan:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86
Yang menghasilkan output yang terlihat mirip dengan:
# .../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",
)
Nama target perangkat menggunakan template ini:
@android_test_support//tools/android/emulated_devices/device_type:system_api_level_x86_qemu2
Untuk meluncurkan android_device
, system_image
untuk API yang dipilih
level wajib diisi. Untuk mendownload image sistem, gunakan atribut
tools/bin/sdkmanager
. Misalnya, untuk mengunduh {i>image<i} sistem untuk
generic_phone:android_23_x86
, jalankan $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86"
.
Untuk melihat daftar lengkap target android_device
yang didukung di
@android_test_support
, jalankan perintah berikut:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'
Bazel saat ini hanya mendukung emulator berbasis x86. Untuk performa yang lebih baik, gunakan
QEMU2
target android_device
bukan QEMU
target.
Menjalankan pengujian
Untuk menjalankan pengujian, tambahkan baris-baris ini ke elemen
File 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
Kemudian, gunakan salah satu konfigurasi untuk menjalankan pengujian:
bazel test //my/test:target --config=gui
bazel test //my/test:target --config=headless
bazel test //my/test:target --config=local_device
Gunakan hanya satu konfigurasi atau pengujian akan gagal.
Pengujian headless
Dengan Xvfb
, pengujian dapat dilakukan dengan emulator tanpa
antarmuka pengguna, yang juga dikenal sebagai pengujian headless. Untuk menonaktifkan antarmuka grafis
saat menjalankan pengujian, teruskan argumen pengujian --enable_display=false
ke Bazel:
bazel test //my/test:target --test_arg=--enable_display=false
Pengujian GUI
Jika variabel lingkungan $DISPLAY
disetel, dimungkinkan untuk mengaktifkan
antarmuka grafis emulator saat pengujian berjalan. Untuk melakukan ini, teruskan
argumen pengujian ini pada Bazel:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAY
Pengujian dengan emulator atau perangkat lokal
Bazel juga mendukung pengujian secara langsung pada emulator yang diluncurkan secara lokal atau
perangkat seluler. Meneruskan flag
--test_strategy=exclusive
dan
--test_arg=--device_broker_type=LOCAL_ADB_SERVER
untuk mengaktifkan mode pengujian lokal.
Jika ada lebih dari satu perangkat yang terhubung, teruskan penanda
--test_arg=--device_serial_number=$device_id
dengan $device_id
adalah ID
perangkat/emulator yang tercantum di adb devices
.
Contoh project
Jika Anda mencari contoh project kanonis, lihat pengujian Android contoh untuk project yang menggunakan Espresso dan UIAutomator.
Penyiapan Espresso
Jika Anda menulis pengujian UI dengan Espresso
(androidx.test.espresso
), Anda dapat menggunakan cuplikan berikut untuk menyiapkan
Ruang kerja Bazel dengan daftar artefak Espresso yang umum digunakan dan
dependensi:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
Salah satu cara untuk mengatur dependensi ini adalah dengan membuat //:test_deps
bersama
library di file project root/BUILD.bazel
Anda:
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",
],
)
Kemudian, tambahkan dependensi yang diperlukan di 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",
],
)
Terakhir, dalam target android_binary
pengujian Anda, tambahkan //:test_deps
dependensi:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
Tips
Membaca log pengujian
Gunakan --test_output=errors
untuk mencetak log jika pengujian gagal, atau
--test_output=all
untuk mencetak semua output pengujian. Jika Anda mencari
log tes individu, buka
$PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName
.
Misalnya, log pengujian untuk project kanonis BasicSample
berada di
bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
, jalankan:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
Hal ini menghasilkan output berikut:
$ 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
Membaca log emulator
Log emulator untuk target android_device
disimpan di /tmp/
direktori dengan nama emulator_xxxxx.log
, dengan xxxxx
adalah
urutan karakter yang
dihasilkan secara acak.
Gunakan perintah ini untuk menemukan log emulator terbaru:
ls -1t /tmp/emulator_*.log | head -n 1
Pengujian terhadap beberapa level API
Jika ingin melakukan pengujian dengan beberapa API level, Anda dapat menggunakan daftar pemahaman untuk membuat target pengujian untuk setiap level API. Contoh:
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]
Masalah umum
- Proses server adb bercabang tidak dihentikan setelah pengujian
- Meskipun pembuatan APK berfungsi di semua platform (Linux, macOS, Windows), pengujian hanya berfungsi di Linux.
- Bahkan dengan
--config=local_adb
, pengguna tetap harus menentukanandroid_instrumentation_test.target_device
. - Jika menggunakan perangkat lokal atau emulator, Bazel tidak meng-uninstal APK setelah melakukan pengujian. Bersihkan paket dengan menjalankan perintah ini:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall