אם אתם חדשים ב-Bazel, התחילו עם המדריך Building Android with Bazel.
איור 1. מריץ בדיקות אינסטרומנטציות מקבילות ב-Android.
android_instrumentation_test
מפתחים יכולים לבדוק את האפליקציות שלהם באמצעות אמולטורים ומכשירים של Android.
המערכת משתמשת בממשקי API אמיתיים של Android ובספריית הבדיקה של Android.
לבנייה והפקה מחדש של Bazel, היא יוצרת ומפעילה אמולטורים של Android בארגז חול כדי להבטיח שהבדיקות תמיד יפעלו ממצב נקי. כל בדיקה מקבלת מופע מבודד של אמולטור שמאפשר להריץ בדיקות בו-זמנית בלי לעבור בין מצבים.
למידע נוסף על בדיקות אינסטרומנטציה ב-Android, אפשר לעיין בתיעוד המפתחים של Android.
יש לשלוח בעיות בכלי למעקב אחר בעיות של GitHub.
איך זה עובד
כשמריצים bazel test
על יעד מסוג android_instrumentation_test
בפעם הראשונה, Bazel מבצעת את הפעולות הבאות:
- יוצר את ה-APK הניסיוני, ה-APK בבדיקה והתלויות בעקיפות
- יוצר, מגפיים ומטמון של מצבי אמולטור נקיים
- הפעלת האמולטור
- התקנת חבילות ה-APK
- מריץ בדיקות על ידי שימוש בכלי הבדיקה של Android
- כיבוי האמולטור
- דיווח על התוצאות
בהרצה הבאה של בדיקות, Bazel מגבירה את האמולטור מהמצב הנקי והמטמון שנוצר בשלב 2, כך שלא נותרו מצבי ריצה מהפעלות קודמות. מצב אמולטור שומר גם על הרצת בדיקות.
דרישות מוקדמות
עליכם לוודא שהסביבה עומדת בדרישות המוקדמות הבאות:
Linux. הבדיקה נערכה ב-Ubuntu 16.04 וב-18.04.
Bazel 0.12.0 ואילך. אמת את הגרסה על ידי הפעלת
bazel info release
.
bazel info release
התוצאה היא פלט הדומה לזה:
release 4.1.0
- KVM . ב-Bazel יש צורך באמולטורים להאצת החומרה באמצעות KVM ב-Linux. אפשר לבצע את הוראות ההתקנה האלה ל-Ubuntu.
כדי לוודא שתצורת ה-KVM היא ההגדרה הנכונה, יש להריץ:
apt-get install cpu-checker && kvm-ok
אם הדפסת את ההודעה הבאה, יש לך את התצורה הנכונה:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. כדי להריץ בדיקות ללא GUI (למשל, בשרתים של CI), ל-Bazel נדרש מאגר הנתונים הווירטואלי של X framework.
כדי להתקין אותו, יש להריץ:
apt-get install xvfb
יש לוודא שאפליקציית Xvfb
מותקנת נכון ושהיא מותקנת ב-/usr/bin/Xvfb
. לשם כך:
which Xvfb
הפלט שיתקבל זהה לפלט הבא:
/usr/bin/Xvfb
- ספריות ב-32 סיביות חלק מהבינאריים המשמשים בתשתית הבדיקה הם בגרסת 32 ביט, לכן במכונות של 64 ביט, אפשר להריץ קבצים בינאריים של 32 ביט. עבור Ubuntu, מתקינים את הספריות הבאות של 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
. יעד זה מתאר את המפרט של אמולטור Android שבו משתמשת Bazel כדי ליצור, להפעיל ולהריץ את הבדיקות. למידע נוסף, ראה קטע 'בחירת מכשיר Android'.
אפליקציית הבדיקה של 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
: ה-SDK של Android. ניתן להוריד את הסרטון דרך Android Studio.@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 מהמאגרים, כמו 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&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
יש להשתמש בתצורה אחת בלבד או שהבדיקות ייכשלו.
בדיקה ללא GUI
באמצעות Xvfb
, ניתן לבצע בדיקות באמצעות אמולטורים ללא הממשק
הגרפי, המכונה גם בדיקה ללא GUI. כדי להשבית את הממשק הגרפי
כשמריצים בדיקות, מעבירים את ארגומנט הבדיקה --enable_display=false
ל-Bazel:
bazel test //my/test:target --test_arg=--enable_display=false
בדיקת GUI
אם משתנה הסביבה $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
.
פרויקטים לדוגמה
אם אתם מחפשים דוגמאות של פרויקטים קנוניים, כדאי לעיין בדוגמאות לבדיקה של Android לפרויקטים באמצעות Espresso ו-UIAutomator.
אספרסו
אם אתם כותבים בדיקות ממשק משתמש באמצעות Espresso
(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(
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]
בעיות ידועות
- תהליכי ההעלאה של שרתי Forbed לא מסתיימים לאחר בדיקות
- מבנה ה-APK פועל בכל הפלטפורמות (Linux, macOS, Windows) אבל הבדיקה פועלת רק ב-Linux.
- גם עם
--config=local_adb
, משתמשים עדיין צריכים לצייןandroid_instrumentation_test.target_device
. - אם נעשה שימוש במכשיר מקומי או באמולטור, Bazel לא מסירה את ה-APKs לאחר הבדיקה. מנקים את החבילות באמצעות הפקודה הבאה:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall