अगर आपने हाल ही में Bazel का इस्तेमाल शुरू किया है, तो Bazel के साथ Android बनाने के बारे में ट्यूटोरियल देखें.
पहला डायग्राम. Android के साथ-साथ चलने वाले इंस्ट्रुमेंटेशन टेस्ट किए जा रहे हैं.
android_instrumentation_test
की मदद से डेवलपर, Android एम्युलेटर और डिवाइसों पर अपने ऐप्लिकेशन की जांच कर सकते हैं.
इसमें, असल Android फ़्रेमवर्क एपीआई और Android Test Library का इस्तेमाल किया जाता है.
हर्मेटिटी और रीप्रॉड्यूसिबिलिटी के लिए, 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
रिपोर्ट का इस्तेमाल करना
यहां 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 एम्युलेटर की उस खास जानकारी के बारे में बताया गया है जिसका इस्तेमाल 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>
वर्कस्पेस डिपेंडेंसी
इस नियम का इस्तेमाल करने के लिए, आपके प्रोजेक्ट को इन बाहरी डेटा स्टोर करने की जगहों पर निर्भर करना होगा:
@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 डिपेंडेंसी
डेटा स्टोर करने की जगहों के मेवन आर्टफ़ैक्ट की डिपेंडेंसी मैनेज करने के लिए, आपको Google
Maven या Maven Central जैसे मेवन रिज़ॉल्वर का इस्तेमाल करना चाहिए. जैसे,
rules_jvm_external
.
इस पेज के बाकी हिस्से में, मेवन डेटा स्टोर करने की जगहों से डिपेंडेंसी तय करने और फ़ेच करने के लिए, 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
की मदद से, ग्राफ़िकल इंटरफ़ेस के बिना एम्युलेटर से टेस्ट किया जा सकता है. इसे बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला टेस्ट भी कहा जाता है. जांच करते समय ग्राफ़िकल इंटरफ़ेस को बंद करने के लिए, Bazel को टेस्ट तर्क --enable_display=false
पास करें:
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
में दिए गए डिवाइस/एम्युलेटर का आईडी है.
सैंपल प्रोजेक्ट
अगर आपको कैननिकल प्रोजेक्ट के सैंपल चाहिए, तो Espresso और UIAutomator का इस्तेमाल करने वाले प्रोजेक्ट के लिए, Android टेस्टिंग सैंपल देखें.
एस्प्रेसो सेट अप
अगर 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
इन डिपेंडेंसी को व्यवस्थित करने का एक तरीका यह है कि आप अपनी 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
टारगेट के लिए एम्युलेटर लॉग, /tmp/
डायरेक्ट्री में emulator_xxxxx.log
नाम के साथ स्टोर किए जाते हैं. यहां 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