अगर आपने Bazel का इस्तेमाल पहले कभी नहीं किया है, तो Bazel के साथ Android बनाना ट्यूटोरियल देखें.
पहला डायग्राम. पैरलल Android इंस्ट्रुमेंटेशन की जांच की जा रही है.
android_instrumentation_test
की मदद से डेवलपर, Android एम्युलेटर और डिवाइसों पर अपने ऐप्लिकेशन की जांच कर सकते हैं.
इसमें, Android टेस्ट लाइब्रेरी और Android फ़्रेमवर्क के असली एपीआई का इस्तेमाल किया जाता है.
हर्मेटिटी और रीप्रॉड्यूसिबिलिटी के लिए, Bazel सैंडबॉक्स में Android एम्युलेटर बनाता और लॉन्च करता है. इससे यह पक्का होता है कि टेस्ट हमेशा सही स्थिति में चलें. हर टेस्ट को एक अलग एम्युलेटर इंस्टेंस मिलता है, जिससे टेस्ट उनके बीच पास किए बिना ही साथ-साथ चल पाते हैं.
Android इंस्ट्रुमेंटेशन टेस्ट के बारे में ज़्यादा जानकारी के लिए, Android डेवलपर दस्तावेज़ देखें.
कृपया GitHub से जुड़ी समस्या को ट्रैक करने वाले टूल में समस्याओं की जानकारी दें.
यह कैसे काम करता है
पहली बार android_instrumentation_test
के टारगेट पर bazel test
चलाने पर, Bazel यह तरीका अपनाता है:
- टेस्ट APK, APK, और उनकी ट्रांज़िटिव डिपेंडेंसी बनाता है
- यह नीति, एम्युलेटर की स्थितियों को सेट करके, चालू करती है, कैश मेमोरी में सेव करती है, और चालू करती है
- एम्युलेटर शुरू करता है
- APK इंस्टॉल करता है
- Android टेस्ट ऑर्केस्ट्रेटर का इस्तेमाल करके टेस्ट करता है
- एम्युलेटर को बंद कर देता है
- नतीजों की रिपोर्ट करता है
बाद में टेस्ट करने पर, Bazel, एम्युलेटर को दूसरे चरण में बनाए गए, कैश मेमोरी में सेव किए गए साफ़ स्टेटस से चालू करता है. ऐसा इसलिए, ताकि पिछली बार चलाए गए डेटा की कोई स्थिति न बची हो. कैश मेमोरी में सेव होने वाले एम्युलेटर की स्थिति में भी, टेस्ट तेज़ हो जाते हैं.
ज़रूरी शर्तें
पक्का करें कि आपका एनवायरमेंट इन शर्तों को पूरा करता हो:
Linux. Ubuntu 16.04, और 18.04 पर टेस्ट किया गया.
Bazel 0.12.0 या उसके बाद के वर्शन.
bazel info release
चलाकर वर्शन की पुष्टि करें.
bazel info release
इससे, आउटपुट कुछ ऐसा मिलता है:
release 4.1.0
- केवीएम. Bazel के लिए ज़रूरी है कि Linux पर केवीएम के साथ, एम्युलेटर का हार्डवेयर एक्सेलरेशन हो. Ubuntu के लिए इंस्टॉल करने के निर्देशों का पालन किया जा सकता है.
यह पुष्टि करने के लिए कि केवीएम का कॉन्फ़िगरेशन सही है, इसे चलाएं:
apt-get install cpu-checker && kvm-ok
अगर यह इस मैसेज को प्रिंट करता है, तो इसका मतलब है कि आपके पास सही कॉन्फ़िगरेशन है:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले टेस्ट (उदाहरण के लिए, सीआई सर्वर) चलाने के लिए, Bazel को X वर्चुअल फ़्रेमबफ़र की ज़रूरत होती है.
इसे इंस्टॉल करने के लिए, इसे चलाएं:
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
YouTube TV का इस्तेमाल शुरू करना
यहां android_instrumentation_test
का सामान्य टारगेट डिपेंडेंसी ग्राफ़ दिया गया है:
दूसरी इमेज. किसी android_instrumentation_test
का टारगेट डिपेंडेंसी ग्राफ़.
बिल्ड फ़ाइल
ग्राफ़, 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 Emulator की उन खास बातों के बारे में बताया गया है जिनका इस्तेमाल 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
: Android SDK. इसे 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 डिपेंडेंसी
डेटा स्टोर करने की जगहों के Maven आर्टफ़ैक्ट की डिपेंडेंसी को मैनेज करने के लिए, आपको
rules_jvm_external
जैसे मेवन रिज़ॉल्वर का इस्तेमाल करना चाहिए. जैसे, Google
Maven या Maven Central.
इस पेज के बाकी हिस्से में, मेवन रिपॉज़िटरी से डिपेंडेंसी पाने और डिपेंडेंसी पाने के लिए rules_jvm_external
का इस्तेमाल करने का तरीका बताया गया है.
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
ज़रूरी है. सिस्टम की इमेज डाउनलोड करने के लिए, Android SDK के
tools/bin/sdkmanager
का इस्तेमाल करें. उदाहरण के लिए, generic_phone:android_23_x86
के लिए सिस्टम इमेज डाउनलोड करने के लिए, $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86"
चलाएं.
@android_test_support
में इस्तेमाल किए जा सकने वाले android_device
टारगेट की पूरी सूची देखने के लिए, यह कमांड चलाएं:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'
फ़िलहाल, Bazel सिर्फ़ x86 पर आधारित एम्युलेटर के साथ काम करता है. बेहतर परफ़ॉर्मेंस के लिए, QEMU
के बजाय QEMU2
android_device
टारगेट का इस्तेमाल करें.
जांच करना
जांच करने के लिए, इन लाइनों को अपने प्रोजेक्ट की 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
एनवायरमेंट वैरिएबल सेट किया गया है, तो टेस्ट के दौरान भी एम्युलेटर के ग्राफ़िकल इंटरफ़ेस को चालू किया जा सकता है. ऐसा करने के लिए, Bzel को ये जांच वाले तर्क पास करें:
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 का इस्तेमाल करने वाले प्रोजेक्ट के लिए, Android टेस्टिंग के सैंपल देखें.
एस्प्रेसो सेटअप
अगर Espresso (androidx.test.espresso
) की मदद से यूज़र इंटरफ़ेस (यूआई) टेस्ट लिखा जाता है, तो आम तौर पर इस्तेमाल होने वाले एस्प्रेसो आर्टफ़ैक्ट और उनकी डिपेंडेंसी के साथ अपना बेज़ल फ़ाइल फ़ोल्डर सेट अप करने के लिए,
इन स्निपेट का इस्तेमाल किया जा सकता है:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
इन डिपेंडेंसी को व्यवस्थित करने का एक तरीका यह है कि अपनी project root/BUILD.bazel
फ़ाइल में //:test_deps
शेयर की गई लाइब्रेरी बनाई जाए:
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
टारगेट के लिए एम्युलेटर लॉग, emulator_xxxxx.log
नाम के साथ /tmp/
डायरेक्ट्री में सेव किए जाते हैं. इसमें xxxxx
वर्णों का बिना किसी क्रम के जनरेट किया गया क्रम होता है.
सबसे नया एम्युलेटर लॉग ढूंढने के लिए, इस कमांड का इस्तेमाल करें:
ls -1t /tmp/emulator_*.log | head -n 1
कई एपीआई लेवल के लिए टेस्ट करना
अगर आपको एक से ज़्यादा एपीआई लेवल की जांच करनी है, तो हर एपीआई लेवल के लिए टेस्ट टारगेट बनाने के लिए, सूची समझने की सुविधा का इस्तेमाल करें. उदाहरण के लिए:
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 बनाने की सुविधा सभी प्लैटफ़ॉर्म (Linux, macOS, Windows) पर काम करती है. हालांकि, टेस्टिंग सिर्फ़ Linux पर काम करती है.
--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