Bazel'i yeni kullanmaya başlıyorsanız Bazel ile Android Uygulaması Geliştirme eğitiminden başlayın.

1. şekil. Paralel Android araç testleri çalıştırma
android_instrumentation_test
Geliştiricilerin uygulamalarını Android emülatörlerinde ve cihazlarında test etmesine olanak tanır.
Gerçek Android çerçeve API'lerini ve Android Test Kitaplığı'nı kullanır.
Bazel, hermetiklik ve tekrarlanabilirlik için Android emülatörlerini bir sanal alanda oluşturup başlatır. Böylece testlerin her zaman temiz bir durumda çalışması sağlanır. Her test için ayrı bir emülatör örneği oluşturulur. Böylece testler, aralarında durum aktarımı olmadan paralel olarak çalışabilir.
Android enstrümantasyon testleri hakkında daha fazla bilgi için Android geliştirici belgelerine göz atın.
Lütfen sorunları GitHub sorun izleyicisinde bildirin.
İşleyiş şekli
bazel test komutunu android_instrumentation_test hedefinde ilk kez çalıştırdığınızda Bazel aşağıdaki adımları gerçekleştirir:
- Test APK'sını, test edilen APK'yı ve bunların geçişli bağımlılıklarını oluşturur.
- Temiz emülatör durumları oluşturur, başlatır ve önbelleğe alır.
- Emülatörü başlatır.
- APK'ları yükler.
- Android Test Orchestrator'ü kullanan testleri çalıştırma
- Emülatörü kapatır.
- Sonuçları bildirir
Sonraki test çalıştırmalarında Bazel, emülatörü 2. adımda oluşturulan temiz, önbelleğe alınmış durumdan başlatır. Bu nedenle, önceki çalıştırmalardan kalan durumlar olmaz. Öykünücü durumunu önbelleğe alma da test çalıştırmalarını hızlandırır.
Ön koşullar
Ortamınızın aşağıdaki ön koşulları karşıladığından emin olun:
Linux. Ubuntu 16.04 ve 18.04'te test edilmiştir.
Bazel 0.12.0 veya sonraki sürümler.
bazel info releasekomutunu çalıştırarak sürümü doğrulayın.
bazel info releaseBu işlem sonucunda şuna benzer bir çıktı elde edilir:
release 4.1.0
- KVM. Bazel, Linux'ta KVM ile donanım hızlandırma özelliğinin emülatörlerde bulunmasını gerektirir. Ubuntu için bu yükleme talimatlarını uygulayabilirsiniz.
KVM'nin doğru yapılandırmaya sahip olduğunu doğrulamak için şunu çalıştırın:
apt-get install cpu-checker && kvm-okAşağıdaki mesajı yazdırıyorsa doğru yapılandırmaya sahipsiniz demektir:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. Başsız testler (ör. CI sunucularında) çalıştırmak için Bazel'in X sanal arabellek çerçevesi gerekir.
Yüklemek için şu komutu çalıştırın:
apt-get install xvfbAşağıdaki komutu çalıştırarak Xvfb'nın doğru şekilde ve /usr/bin/Xvfb konumuna yüklendiğini doğrulayın:
which XvfbÇıkış şu şekildedir:
/usr/bin/Xvfb
- 32 bit kitaplıklar. Test altyapısı tarafından kullanılan ikili dosyaların bazıları 32 bit olduğundan 64 bit makinelerde 32 bit ikili dosyaların çalıştırılabildiğinden emin olun. Ubuntu için şu 32 bit kitaplıkları yükleyin:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386Başlarken
android_instrumentation_test için tipik bir hedef bağımlılığı grafiği aşağıda verilmiştir:

Şekil 2. android_instrumentation_test öğesinin hedef bağımlılık grafiği.
BUILD dosyası
Grafik, şu şekilde bir BUILD dosyasına dönüştürülür:
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",
]
# ...
)
Kuralın android_instrumentation_test temel özellikleri şunlardır:
test_app:android_binaryhedefi. Bu hedef, test kodu ve Espresso ile UIAutomator gibi bağımlılıkları içerir. Seçilenandroid_binaryhedefinin, test edilen uygulama olan başka birandroid_binary'ya işaret eden birinstrumentsözelliği belirtmesi gerekir.target_device:android_devicehedefi. Bu hedef, Bazel'in testleri oluşturmak, başlatmak ve çalıştırmak için kullandığı Android emülatörünün özelliklerini açıklar. Daha fazla bilgi için Android cihaz seçme bölümüne bakın.
Test uygulamasının AndroidManifest.xml bölümünde bir <instrumentation> etiketi bulunmalıdır.
Bu etiket, hedef uygulamanın paketine ve enstrümantasyon testi çalıştırıcısının tam nitelikli sınıf adına ait özellikleri belirtmelidir.androidx.test.runner.AndroidJUnitRunner.
Test uygulaması için örnek bir AndroidTestManifest.xml aşağıda verilmiştir:
<?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>
WORKSPACE bağımlılıkları
Bu kuralı kullanabilmek için projenizin şu harici depolara bağlı olması gerekir:
@androidsdk: Android SDK'sı. Bunu Android Studio üzerinden indirin.@android_test_support: Test çalıştırıcıyı, emülatör başlatıcıyı veandroid_devicehedeflerini barındırır. En son sürümü burada bulabilirsiniz.
Aşağıdaki satırları WORKSPACE dosyanıza ekleyerek bu bağımlılıkları etkinleştirin:
# 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()
Maven bağımlılıkları
Google Maven veya Maven Central gibi depolardaki Maven yapılarında bağımlılıkları yönetmek için rules_jvm_external gibi bir Maven çözümleyici kullanmanız gerekir.
Bu sayfanın geri kalanında, Maven depolarındaki bağımlılıkları çözmek ve getirmek için rules_jvm_external'nın nasıl kullanılacağı gösterilmektedir.
android_device hedefi seçme
android_instrumentation_test.target_device testlerin hangi Android cihazda çalıştırılacağını belirtir. Bu android_device hedefleri @android_test_support içinde tanımlanır.
Örneğin, belirli bir hedefin kaynaklarını sorgulamak için şu komutu çalıştırabilirsiniz:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86Bu işlem, aşağıdakine benzer bir çıkışla sonuçlanır:
# .../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",
)
Cihaz hedef adları şu şablonu kullanır:
@android_test_support//tools/android/emulated_devices/device_type:system_api_level_x86_qemu2
android_device başlatmak için seçilen API düzeyine yönelik system_image gereklidir. Sistem görüntüsünü indirmek için Android SDK'nın tools/bin/sdkmanager aracını kullanın. Örneğin, generic_phone:android_23_x86 için sistem görüntüsünü indirmek üzere $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86" komutunu çalıştırın.
android_device'da desteklenen @android_test_support hedeflerinin tam listesini görmek için aşağıdaki komutu çalıştırın:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'Bazel şu anda yalnızca x86 tabanlı emülatörleri desteklemektedir. Daha iyi performans için QEMU hedefleri yerine QEMU2 android_device hedeflerini kullanın.
Testleri çalıştırma
Testleri çalıştırmak için projenizin project root:/.bazelrc dosyasına bu satırları ekleyin.
# 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
Ardından, testleri çalıştırmak için aşağıdaki yapılandırmalardan birini kullanın:
bazel test //my/test:target --config=guibazel test //my/test:target --config=headlessbazel test //my/test:target --config=local_device
Yalnızca bir yapılandırma kullanın. Aksi takdirde testler başarısız olur.
Gözetimsiz test
Xvfb ile, grafik arayüzü olmadan emülatörlerle test yapmak mümkündür. Bu işleme, başsız test de denir. Testleri çalıştırırken grafik arayüzünü devre dışı bırakmak için Bazel'e --enable_display=false test bağımsız değişkenini iletin:
bazel test //my/test:target --test_arg=--enable_display=falseGUI testi
$DISPLAY ortam değişkeni ayarlanmışsa test çalışırken emülatörün grafik arayüzünü etkinleştirmek mümkündür. Bunu yapmak için aşağıdaki test bağımsız değişkenlerini Bazel'e iletin:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAYYerel bir emülatör veya cihazla test etme
Bazel, yerel olarak başlatılan bir emülatörde veya bağlı bir cihazda doğrudan test yapmayı da destekler. Yerel test modunu etkinleştirmek için --test_strategy=exclusive ve --test_arg=--device_broker_type=LOCAL_ADB_SERVER işaretlerini iletin.
Birden fazla bağlı cihaz varsa --test_arg=--device_serial_number=$device_id işaretini iletin. Burada $device_id, adb devices içinde listelenen cihazın/emülatörün kimliğidir.
Örnek projeler
Standart proje örnekleri arıyorsanız Espresso ve UIAutomator kullanan projeler için Android test örneklerine bakın.
Espresso kurulumu
Espresso ile kullanıcı arayüzü testleri yazıyorsanız
(androidx.test.espresso) Bazel çalışma alanınızı yaygın olarak kullanılan Espresso yapıları ve bunların bağımlılıklarının listesiyle ayarlamak için aşağıdaki snippet'leri kullanabilirsiniz:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
Bu bağımlılıkları düzenlemenin bir yolu, //:test_deps dosyanızda //:test_deps paylaşılan bir kitaplık oluşturmaktır: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",
],
)
Ardından, project root/WORKSPACE konumuna gerekli bağımlılıkları ekleyin:
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",
],
)
Son olarak, test android_binary hedefinizde //:test_deps
bağımlılığını ekleyin:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
İpuçları
Okuma testi günlükleri
Başarısız olan testlerin günlüklerini yazdırmak için --test_output=errors, tüm test çıkışını yazdırmak için --test_output=all kullanın. Tek bir test günlüğü arıyorsanız $PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName bölümüne gidin.
Örneğin, BasicSample standart projesinin test günlükleri bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest içinde bulunur.
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTestBu durumda aşağıdaki çıkış elde edilir:
$ 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
Emülatör günlüklerini okuma
android_device hedeflerine yönelik emülatör günlükleri, /tmp/ dizininde emulator_xxxxx.log adıyla saklanır. Burada xxxxx, rastgele oluşturulmuş bir karakter dizisidir.
En son emülatör günlüğünü bulmak için bu komutu kullanın:
ls -1t /tmp/emulator_*.log | head -n 1Birden fazla API düzeyine göre test etme
Birden fazla API düzeyine karşı test yapmak istiyorsanız her API düzeyi için test hedefleri oluşturmak üzere liste kapsamı kullanabilirsiniz. Örneğin:
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]
Bilinen sorunlar
- Çatal oluşturulmuş adb sunucu işlemleri, testlerden sonra sonlandırılmıyor
- APK oluşturma tüm platformlarda (Linux, macOS, Windows) çalışırken test etme yalnızca Linux'ta çalışır.
--config=local_adbolsa bile kullanıcılarınandroid_instrumentation_test.target_devicebelirtmesi gerekir.- Yerel bir cihaz veya emülatör kullanılıyorsa Bazel, testten sonra APK'ları kaldırmaz. Şu komutu çalıştırarak paketleri temizleyin:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall