Android Enstrümantasyon Testleri

Sorun bildir Kaynağı göster Gece · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Bazel'i kullanmaya yeni başladıysanız Android ile Bazel eğitimi.

Android araç testlerini paralel olarak çalıştırma

Şekil 1. Paralel Android araç testleri yapılıyor.

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ştirdi ve piyasaya sürdü 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 araç testleri hakkında daha fazla bilgi için Android geliştirici dokümanlarına göz atın.

Lütfen sorunları GitHub sorun izleyiciye gönderin.

İşleyiş şekli

Şu öğe için android_instrumentation_test hedefinde bazel test çalıştırdığınızda: ilk kez kullandığınızda, Bazel aşağıdaki adımları uygular:

  1. Test APK'sını, test edilen APK'yı ve bunların geçişli bağımlılıklarını oluşturur
  2. Temiz emülatör durumları oluşturur, başlatır ve önbelleğe alır
  3. Emülatörü başlatır
  4. APK'ları yükler
  5. Android Test Orchestrator'ı kullanarak testler çalıştırır.
  6. Emülatörü kapatır
  7. 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. Önbelleğe alma emülatör durumu, test çalıştırmalarını da 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'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 gösteriliyorsa yapılandırma doğrudur:

INFO: /dev/kvm exists
KVM acceleration can be used

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

Aşağıda android_instrumentation_test için tipik bir hedef bağımlılık grafiği verilmiştir:

Bir Android araç testindeki hedef bağımlılık grafiği

Şekil 2. android_instrumentation_test 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 hedefidir. Bu hedef, test kodunu ve ve UIAutomator gibi bağımlılıkları ifade eder. Seçilen android_binary başka bir kullanıcıya işaret eden instruments özelliğini belirtmek için hedef gerekir Test edilen uygulama olan android_binary.

  • target_device: android_device hedefidir. Bu hedef, Bazel'in kullandığı Android emülatörünün teknik özellikleri yapmanız gerekir. Android cihaz seçme ile ilgili bölüme bakın. cihaz başlıklı makaleyi inceleyin.

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ı kullanmak için projenizin bu harici kaynaklar depolar:

  • @androidsdk: Android SDK'sı. Bunu Android Studio'dan indirin.

  • @android_test_support: Test çalıştırıcısını, emülatör başlatıcıyı ve android_device hedef. 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 Cloud Search gibi depolardaki Maven yapılarına olan bağımlılıkları yönetmek için Maven veya Maven Central, Gmail çözümleyicisi kullanın: rules_jvm_external.

Bu sayfanın geri kalanında, rules_jvm_external yönergesini kullanarak Maven depolarından bağımlılıkları çözümleyip getirin.

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 hedef şurada tanımlanmıştır: @android_test_support

Örneğin, aşağıdaki komutu çalıştırarak belirli bir hedefe ilişkin kaynakları 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 Örneğin, generic_phone:android_23_x86, $sdk/tools/bin/sdkmanager "system-images;android-23;default;x86". koşu.

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 QEMU2 QEMU hedef yerine android_device hedef.

Testler yapılıyor

Testler yapmak için bu satırları projenizin project root:/.bazelrc dosyası yükleyin.

# 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'e 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 ayrıca doğrudan yerel olarak başlatılan bir emülatörde veya olanak tanır. İş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 işareti iletin $device_id, --test_arg=--device_serial_number=$device_id kimliğidir adb devices içinde listelenen cihaz/emülatör.

Ö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ı ve bağımlılıkları vardır:

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, ortak bir //:test_deps project root/BUILD.bazel dosyanıza ekleyin:

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 komutuna 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. Bir test günlüğüne gidin, $PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName

Örneğin, BasicSample standart projesinin test günlükleri şu konumdadır: bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest, çalıştırma:

tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest

Bu işlem sonucunda şu çı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 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

  • Çatallı adb sunucusu işlemleri testler
  • APK oluşturma tüm platformlarda (Linux, macOS, Windows) çalışırken yalnızca Linux'ta çalışır.
  • --config=local_adb olsa bile kullanıcıların android_instrumentation_test.target_device.
  • 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