اگر تازه وارد بازل هستید، با آموزش ساخت اندروید با بازل شروع کنید.
شکل 1. اجرای تست های موازی ابزار دقیق اندروید.
android_instrumentation_test
به توسعه دهندگان این امکان را می دهد تا برنامه های خود را روی شبیه سازها و دستگاه های Android آزمایش کنند. از APIهای فریمورک اندروید واقعی و کتابخانه تست اندروید استفاده می کند.
برای هرمتیک بودن و تکرارپذیری، Bazel شبیهسازهای اندروید را در یک جعبه شنی ایجاد و راهاندازی میکند تا اطمینان حاصل کند که آزمایشها همیشه از حالت تمیز اجرا میشوند. هر تست یک نمونه شبیه ساز جدا شده را دریافت می کند که به تست ها اجازه می دهد به صورت موازی بدون عبور از حالت های بین آنها اجرا شوند.
برای اطلاعات بیشتر در مورد تستهای ابزار دقیق Android، مستندات برنامهنویس Android را بررسی کنید.
لطفاً مشکلات را در ردیاب مشکل GitHub ثبت کنید.
چگونه کار می کند
وقتی برای اولین بار bazel test
روی هدف android_instrumentation_test
اجرا می کنید، Bazel مراحل زیر را انجام می دهد:
- APK آزمایشی، APK تحت آزمایش و وابستگیهای گذرا آنها را میسازد
- حالت های شبیه ساز تمیز را ایجاد، راه اندازی و ذخیره می کند
- شبیه ساز را راه اندازی می کند
- APK ها را نصب می کند
- با استفاده از Android Test Orchestrator تست ها را اجرا می کند
- شبیه ساز را خاموش می کند
- نتایج را گزارش می دهد
در اجرای آزمایشی بعدی، Bazel شبیه ساز را از حالت پاک و کش ایجاد شده در مرحله 2 بوت می کند، بنابراین هیچ حالت باقیمانده ای از اجرای قبلی وجود ندارد. حالت شبیه ساز کش نیز سرعت اجرای آزمایشی را افزایش می دهد.
پیش نیازها
اطمینان حاصل کنید که محیط شما پیش نیازهای زیر را برآورده می کند:
لینوکس . تست شده در اوبونتو 16.04 و 18.04.
Bazel 0.12.0 یا بالاتر. با اجرای
bazel info release
، نسخه را تأیید کنید.
bazel info release
این نتیجه خروجی مشابه زیر را دارد:
release 4.1.0
- KVM . Bazel به شبیه سازها نیاز دارد که شتاب سخت افزاری با KVM در لینوکس داشته باشند. می توانید این دستورالعمل های نصب را برای اوبونتو دنبال کنید.
برای تأیید اینکه KVM پیکربندی صحیحی دارد، اجرا کنید:
apt-get install cpu-checker && kvm-ok
اگر پیغام زیر را چاپ کند، پیکربندی صحیح را دارید:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb . برای اجرای آزمایشهای بدون سر (به عنوان مثال، روی سرورهای CI)، Bazel به فریمبافر مجازی X نیاز دارد.
برای نصب آن، اجرا کنید:
apt-get install xvfb
/usr/bin/Xvfb
Xvfb
:
which Xvfb
خروجی به صورت زیر است:
/usr/bin/Xvfb
- کتابخانه های 32 بیتی برخی از باینری های استفاده شده توسط زیرساخت تست 32 بیتی هستند، بنابراین در ماشین های 64 بیتی، اطمینان حاصل کنید که باینری های 32 بیتی قابل اجرا هستند. برای اوبونتو، این کتابخانه های 32 بیتی را نصب کنید:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
شروع شدن
در اینجا یک نمودار وابستگی هدف معمولی یک android_instrumentation_test
است:
شکل 2. نمودار وابستگی هدف یک android_instrumentation_test
.
فایل BUILD
نمودار به یک فایل BUILD
مانند این ترجمه می شود:
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
عبارتند از:
test_app
: یک هدفandroid_binary
. این هدف حاوی کد تست و وابستگی هایی مانند Espresso و UIAutomator است. هدفandroid_binary
انتخاب شده برای مشخص کردن یک ویژگیinstruments
بهandroid_binary
دیگر، که برنامه تحت آزمایش است، مورد نیاز است.target_device
: یک هدفandroid_device
. این هدف مشخصات شبیهساز اندروید را که Bazel برای ایجاد، راهاندازی و اجرای تستها استفاده میکند، توصیف میکند. برای اطلاعات بیشتر به بخش انتخاب دستگاه اندروید مراجعه کنید.
AndroidManifest.xml
برنامه آزمایشی باید دارای یک برچسب <instrumentation>
باشد. این تگ باید ویژگیهای بسته برنامه هدف و نام کلاس کاملاً واجد شرایط رانر تست ابزار دقیق ، androidx.test.runner.AndroidJUnitRunner
کند.
در اینجا یک مثال AndroidTestManifest.xml
برای برنامه آزمایشی آورده شده است:
<?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
برای استفاده از این قانون، پروژه شما باید به این مخازن خارجی وابسته باشد:
@androidsdk
: Android SDK. این را از طریق اندروید استودیو دانلود کنید.@android_test_support
: میزبان آزمایشکننده، راهانداز شبیهساز و اهدافandroid_device
است. می توانید آخرین نسخه را اینجا پیدا کنید.
این وابستگی ها را با افزودن خطوط زیر به فایل WORKSPACE
خود فعال کنید:
# 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
برای مدیریت وابستگیها به آرتیفکتهای Maven از مخازن، مانند Google Maven یا Maven Central ، باید از حلکننده Maven، مانند rules_jvm_external
استفاده کنید.
بقیه این صفحه نحوه استفاده از rules_jvm_external
را برای رفع و واکشی وابستگی ها از مخازن Maven نشان می دهد.
انتخاب هدف android_device
android_instrumentation_test.target_device
مشخص می کند که تست ها را روی کدام دستگاه Android اجرا کند. این اهداف android_device
در @android_test_support
تعریف شدهاند.
به عنوان مثال، میتوانید منابع یک هدف خاص را با اجرای زیر جستجو کنید:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86
که منجر به خروجی مشابه می شود:
# .../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",
)
نام های هدف دستگاه از این الگو استفاده می کنند:
@android_test_support//tools/android/emulated_devices/device_type:system_api_level_x86_qemu2
برای راهاندازی android_device
، system_image
برای سطح API انتخابشده مورد نیاز است. برای دانلود تصویر سیستم، از Android SDK's tools/bin/sdkmanager
استفاده کنید. به عنوان مثال، برای دانلود تصویر سیستم برای generic_phone:android_23_x86
، $sdk/tools/bin/sdkmanager "system-images;android-23;default;x86"
را اجرا کنید.
برای مشاهده لیست کامل اهداف android_device
پشتیبانی شده در @android_test_support
، دستور زیر را اجرا کنید:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'
Bazel در حال حاضر فقط از شبیه سازهای مبتنی بر x86 پشتیبانی می کند. برای عملکرد بهتر، از QEMU2
android_device
به جای اهداف QEMU
استفاده کنید.
در حال اجرای تست ها
برای اجرای تست ها، این خطوط را به فایل 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
سپس، از یکی از تنظیمات برای اجرای تست ها استفاده کنید:
-
bazel test //my/test:target --config=gui
-
bazel test //my/test:target --config=headless
-
bazel test //my/test:target --config=local_device
فقط از یک پیکربندی استفاده کنید در غیر این صورت آزمایش ها شکست خواهند خورد.
تست بدون سر
با Xvfb
، امکان تست با شبیه سازها بدون رابط گرافیکی وجود دارد که به عنوان تست بدون هد نیز شناخته می شود. برای غیرفعال کردن رابط گرافیکی هنگام اجرای تستها، آرگومان تست --enable_display=false
را به Bazel ارسال کنید:
bazel test //my/test:target --test_arg=--enable_display=false
تست رابط کاربری گرافیکی
اگر متغیر محیط $DISPLAY
تنظیم شده باشد، میتوان رابط گرافیکی شبیهساز را در حین اجرای آزمایش فعال کرد. برای انجام این کار، این آرگومان های آزمایشی را به Bazel ارسال کنید:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAY
تست با شبیه ساز یا دستگاه محلی
Bazel همچنین از آزمایش مستقیم روی یک شبیه ساز محلی یا دستگاه متصل پشتیبانی می کند. برای فعال کردن حالت تست محلی، پرچمهای --test_strategy=exclusive
و --test_arg=--device_broker_type=LOCAL_ADB_SERVER
را پاس دهید. اگر بیش از یک دستگاه متصل وجود دارد، پرچم را ارسال کنید --test_arg=--device_serial_number=$device_id
که در آن $device_id
شناسه دستگاه/شبیه ساز فهرست شده در adb devices
.
نمونه پروژه ها
اگر به دنبال نمونههای پروژه متعارف هستید، نمونههای تست اندروید برای پروژههای با استفاده از Espresso و UIAutomator را ببینید.
تنظیم اسپرسو
اگر تستهای رابط کاربری را با اسپرسو مینویسید ( androidx.test.espresso
)، میتوانید از قطعههای زیر برای تنظیم فضای کاری Bazel خود با فهرستی از مصنوعات اسپرسو رایج و وابستگیهای آنها استفاده کنید:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
یکی از راههای سازماندهی این وابستگیها ایجاد یک کتابخانه مشترک //:test_deps
در فایل 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",
],
)
سپس، وابستگی های مورد نیاز را در 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",
],
)
در نهایت، در هدف Android_binary آزمایشی خود، وابستگی //:test_deps
android_binary
اضافه کنید:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
نکات
خواندن گزارش های تست
از --test_output=errors
برای چاپ لاگ برای تست های ناموفق یا --test_output=all
برای چاپ تمام خروجی های آزمایشی استفاده کنید. اگر به دنبال یک گزارش آزمایشی فردی هستید، به $PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName
.
برای مثال، گزارشهای آزمایشی برای پروژه متعارف BasicSample
در bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
، اجرا کنید:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
این منجر به خروجی زیر می شود:
$ 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
خواندن گزارش های شبیه ساز
گزارشهای شبیهساز برای اهداف android_device
در فهرست /tmp/
با نام emulator_xxxxx.log
ذخیره میشوند، جایی که xxxxx
دنبالهای از کاراکترها بهطور تصادفی تولید شده است.
از این دستور برای یافتن آخرین گزارش شبیه ساز استفاده کنید:
ls -1t /tmp/emulator_*.log | head -n 1
تست در برابر چندین سطح API
اگر میخواهید با چندین سطح API آزمایش کنید، میتوانید از درک فهرست برای ایجاد اهداف آزمایشی برای هر سطح API استفاده کنید. مثلا:
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]
مشکلات شناخته شده
- فرآیندهای سرور adb فورک شده پس از آزمایش خاتمه نمییابند
- در حالی که ساختن APK روی همه پلتفرم ها (لینوکس، macOS، ویندوز) کار می کند، آزمایش فقط روی لینوکس کار می کند.
- حتی با
--config=local_adb
، کاربران همچنان بایدandroid_instrumentation_test.target_device
را مشخص کنند. - در صورت استفاده از یک دستگاه یا شبیهساز محلی، Bazel پس از آزمایش فایلهای APK را حذف نصب نمیکند. با اجرای این دستور بسته ها را پاک کنید:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall