Bazel'i kullanmaya yeni başladıysanız Android ile Bazel eğitimi.
Şekil 1. Paralel Android araç testleri çalıştırma.
android_instrumentation_test
geliştiricilerin uygulamalarını Android emülatörlerinde ve cihazlarda test etmelerine olanak tanır.
Gerçek Android çerçevesi API'lerini ve Android Test Kitaplığı'nı kullanır.
Hermetiklik ve yeniden üretilebilirlik için Bazel, Android'i geliştirip kullanıma sundu. emülatörleri kullanarak testlerin her zaman temiz bir durumda çalışmasını sağlar. Her biri test, izole bir emülatör örneği alır ve testlerin paralel olarak çalıştırılmasına olanak tanır iletmenizi sağlar.
Android enstrümantasyon testleri hakkında daha fazla bilgi için Android geliştirici belgelerine göz atın.
Lütfen GitHub sorun izleyicisinde sorun bildirin.
İşleyiş şekli
bazel test
'ü bir 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'ı kullanarak testler çalıştırır.
- Emülatörü kapatır
- Sonuçları bildirir
Sonraki test çalıştırmalarında Bazel, emülatörü temiz, önbelleğe alınmış durumdan başlatır Böylece önceki çalıştırmalardan kalan durumlar olmaz. Emülatör durumunu önbelleğe almak da test çalıştırma işlemlerini 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 release
komutunu çalıştırarak sürümü doğrulayın.
bazel info release
Bu işlemden sonra şuna benzer bir çıkış elde edilir:
release 4.1.0
- KVM'ye gidin. Bazel, Linux'da KVM ile emülatörlerin donanım hızlandırması kullanmasını gerektirir. Bunları takip edebilirsiniz kurulum talimatları kullanıyor.
KVM'nin doğru yapılandırmaya sahip olduğunu doğrulamak için aşağıdaki komutu çalıştırın:
apt-get install cpu-checker && kvm-ok
Aşağıdaki mesaj yazdırılıyorsa doğru yapılandırmaya sahipsiniz demektir:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb olmalıdır. Bazel, başsız testleri (ör. CI sunucularında) çalıştırmak için X sanal çerçeve arabelleğinin kullanılmasını gerektirir.
Yüklemek için şu komutu çalıştırın:
apt-get install xvfb
Xvfb
adlı uygulamanın doğru şekilde yüklendiğini ve /usr/bin/Xvfb
adresine yüklendiğini doğrulayın
şunu çalıştırarak:
which Xvfb
Çıkış şu şekildedir:
/usr/bin/Xvfb
- 32 bit kitaplıklar. Test altyapısı tarafından kullanılan ikili programlardan bazıları şunlardır: 32 bit (yani 64 bit makinelerde) 32 bit ikili programların çalıştırılabileceğinden emin olun. Örneğin, Ubuntu, şu 32 bit kitaplıkları yükleyin:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
Başlarken
Bir android_instrumentation_test
'ün tipik hedef bağımlılık grafiği aşağıda verilmiştir:
Şekil 2. Bir android_instrumentation_test
'ün hedef bağımlılık grafiği.
BUILD dosyası
Grafik şuna benzer bir BUILD
dosyasına dönüşü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",
]
# ...
)
android_instrumentation_test
kuralının ana özellikleri şunlardır:
test_app
:android_binary
hedefi. Bu hedef, test kodunu ve ve UIAutomator gibi bağımlılıkları ifade eder. Seçilenandroid_binary
başka bir kullanıcıya işaret edeninstruments
özelliğini belirtmek için hedef gerekir Test edilen uygulama olanandroid_binary
.target_device
:android_device
hedefi. 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
öğesi bir <instrumentation>
içermelidir
etiketi kullanın.
Bu etiket, hedef uygulama paketinin özelliklerini belirtmelidir ve
araç test çalıştırıcısının tam nitelikli sınıf adı,
androidx.test.runner.AndroidJUnitRunner
.
Test uygulaması için aşağıda örnek bir AndroidTestManifest.xml
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ı kullanabilmeniz için projenizin aşağıdaki harici depolara bağlı olması gerekir:
@androidsdk
: Android SDK'sı. Bu dosyayı Android Studio üzerinden indirin.@android_test_support
: Test çalıştırıcıyı, emülatör başlatıcıyı veandroid_device
hedefleri 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.
dosya:
# 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ına yönelik bağımlılıkları yönetmek için rules_jvm_external
gibi bir Maven çözümleyicisi kullanmanız gerekir.
Bu sayfanın geri kalanında, Maven depolarından bağımlılıkları çözmek ve almak için rules_jvm_external
'ün nasıl kullanılacağı gösterilmektedir.
android_device hedefi seçme
android_instrumentation_test.target_device
, hangi Android cihazın kullanılacağını belirtir
yapmaktan ibaret değildir. Bu android_device
hedefleri @android_test_support
içinde tanımlanır.
Örneğin, aşağıdakileri çalıştırarak belirli bir hedefin kaynaklarını sorgulayabilirsiniz:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86
Bu durumda şuna benzer bir çıkış elde edilir:
# .../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 hedefi adları şu şablonu kullanır:
@android_test_support//tools/android/emulated_devices/device_type:system_api_level_x86_qemu2
Bir android_device
başlatmak için seçili API'ye ait system_image
,
seviye gerekli. Sistem görüntüsünü indirmek için Android SDK'sı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"
dosyasını çalıştırın.
Desteklenen android_device
hedefin tam listesini görmek için:
@android_test_support
kullanıyorsanız 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
hedefleri kullanın.
Testler yapılıyor
Testleri çalıştırmak için bu satırları projenizin project root:/.bazelrc
dosyasına 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 yapılandırmalardan birini kullanın:
bazel test //my/test:target --config=gui
bazel test //my/test:target --config=headless
bazel 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 olmadan emülatörlerle test yapmak
gözetimsiz test olarak da bilinir. Grafik arayüzü devre dışı bırakmak için
testleri çalıştırırken --enable_display=false
test bağımsız değişkenini Bazel'a iletin:
bazel test //my/test:target --test_arg=--enable_display=false
GUI testi
$DISPLAY
ortam değişkeni ayarlanırsa
test sırasında emülatörün grafik arayüzü. Bunun için
aşağıdaki test bağımsız değişkenlerini Bazel'a bildirir:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAY
Yerel bir emülatör veya cihazla test etme
Bazel, doğrudan yerel olarak başlatılan bir emülatörde veya bağlı cihazda test yapmayı da destekler. İşaretleri geçin
--test_strategy=exclusive
ve
Yerel test modunu etkinleştirmek için --test_arg=--device_broker_type=LOCAL_ADB_SERVER
.
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 Android testi örnekler .
Espresso kurulumu
Espresso ile kullanıcı arayüzü testleri yazarsanız
(androidx.test.espresso
) kullanıyorsanız,
Yaygın olarak kullanılan Espresso eserlerini ve bunların listesini içeren Bazel çalışma alanı
dependencies:
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, project root/BUILD.bazel
dosyanızda //:test_deps
paylaşılan kitaplık oluşturmaktır:
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
dosyasına 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
hedefinize //:test_deps
ekleyin.
bağımlılık:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
İpuçları
Test günlüklerini okuma
Başarısız olan testlere ait günlükleri yazdırmak için --test_output=errors
komutunu kullanın veya
Tüm test çıkışını yazdırmak için --test_output=all
tuşlarına basın. Ayrı bir test günlüğü arıyorsanız $PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName
adresine gidin.
Örneğin, BasicSample
standart projesinin test günlükleri bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
içindeyse şunları çalıştırın:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
Bu işlem şu çıktıyla sonuçlanır:
$ 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
hedeflerinin emülatör günlükleri /tmp/
içinde depolanır
emulator_xxxxx.log
adlı dizin; burada xxxxx
bir değerdir:
rastgele oluşturulmuş karakter dizisi.
En son emülatör günlüğünü bulmak için şu komutu kullanın:
ls -1t /tmp/emulator_*.log | head -n 1
Birden çok API düzeyiyle test etme
Birden çok API düzeyinde test yapmak isterseniz bir liste kullanabilirsiniz her API düzeyi için test hedefleri oluşturmayı öğreneceksiniz. Ö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
- Çatallanmış adb sunucu işlemleri testlerden sonra sonlandırılmıyor
- APK oluşturma tüm platformlarda (Linux, macOS, Windows) çalışırken test yalnızca Linux'ta çalışır.
--config=local_adb
olsa bile kullanıcılarınandroid_instrumentation_test.target_device
'ü belirtmesi gerekir.- Yerel cihaz veya emülatör kullanıyorsanız Bazel, APK'ların yüklemesini deneyin. Ş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