Android इंस्ट्रूमेंटेशन टेस्ट

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

अगर आपने Bazel का इस्तेमाल पहले कभी नहीं किया है, तो Bazel की मदद से Android बनाना ट्यूटोरियल से शुरुआत करें.

Android इंस्ट्रूमेंटेशन टेस्ट को एक साथ चलाना

पहला डायग्राम. साथ-साथ चलने वाले Android इंस्ट्रुमेंटेशन की जांच कर रहे हैं.

android_instrumentation_test इससे डेवलपर, Android एम्युलेटर और डिवाइसों पर अपने ऐप्लिकेशन की जांच कर सकते हैं. यह Android फ़्रेमवर्क के असली एपीआई और Android टेस्ट लाइब्रेरी का इस्तेमाल करता है.

Bazel, सैंडबॉक्स में Android इम्युलेटर बनाता और लॉन्च करता है. इससे, यह पक्का किया जाता है कि टेस्ट हमेशा एक ही स्टेटस में चलें. हर टेस्ट के लिए, एक अलग इम्यूलेटर इंस्टेंस मिलता है. इससे टेस्ट, एक-दूसरे के स्टेटस को पास किए बिना, एक साथ चल सकते हैं.

Android इंस्ट्रुमेंटेशन टेस्ट के बारे में ज़्यादा जानकारी के लिए, Android डेवलपर दस्तावेज़ में दिया गया है.

कृपया GitHub में समस्या को ट्रैक करने वाले टूल में समस्याओं की शिकायत करें.

यह कैसे काम करता है

जब आप android_instrumentation_test के टारगेट पर bazel test चलाते हैं पहली बार, Basel ने इन चरणों को पूरा किया:

  1. टेस्ट APK, जांचा जा रहा APK, और उनकी ट्रांज़िशन डिपेंडेंसी बनाता है
  2. क्लीन एम्युलेटर स्टेट को बनाता है, चालू करता है, और कैश मेमोरी में सेव करता है
  3. एम्युलेटर को शुरू करता है
  4. APK इंस्टॉल करता है
  5. Android Test Orchestrator का इस्तेमाल करके, जांच की जाती है.
  6. एम्युलेटर को बंद करता है
  7. नतीजों की रिपोर्ट करता है

बाद के टेस्ट चलाने के दौरान, Basel ने एम्युलेटर को कैश मेमोरी की क्लीन स्थिति से चालू किया को चरण 2 में बनाया गया है, इसलिए पिछली बार चलाए गए डेटा की कोई स्थिति नहीं बची है. एमुलेटर की स्थिति को कैश मेमोरी में सेव करने से, टेस्ट रन की प्रोसेस तेज़ होती है.

ज़रूरी शर्तें

पक्का करें कि आपका एनवायरमेंट इन ज़रूरी शर्तों को पूरा करता हो:

  • Linux. Ubuntu 16.04 और 18.04 पर टेस्ट किया गया.

  • Bazel 0.12.0 या उसके बाद का वर्शन. bazel info release चलाकर वर्शन की पुष्टि करें.

bazel info release

इससे आउटपुट कुछ ऐसा मिलता है:

release 4.1.0

यह पुष्टि करने के लिए कि केवीएम का कॉन्फ़िगरेशन सही है, इसे चलाएं:

apt-get install cpu-checker && kvm-ok

अगर यह नीचे दिया गया मैसेज प्रिंट करता है, तो इसका मतलब है कि आपके पास सही कॉन्फ़िगरेशन है:

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

इसे इंस्टॉल करने के लिए, इसे चलाएं:

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 इंस्ट्रूमेंटेशन टेस्ट पर टारगेट डिपेंडेंसी ग्राफ़

दूसरी इमेज. 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 टारगेट के लिए, किसी दूसरे android_binary पर ले जाने वाला instruments एट्रिब्यूट तय करना ज़रूरी है. यह android_binary, टेस्ट किया जा रहा ऐप्लिकेशन होता है.

  • target_device: android_device टारगेट. इस टारगेट में, की खास जानकारी, Android Emulator की खास जानकारी है. Basel ने इस ऐप्लिकेशन को बनाने, लॉन्च करने, और टेस्ट करना चाहिए. किसी 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 जैसी रिपॉज़िटरी से Maven आर्टफ़ैक्ट पर डिपेंडेंसी मैनेज करने के लिए, आपको 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 ज़रूरी है. सिस्टम इमेज डाउनलोड करने के लिए, 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 को Baज़र में पास करें:

bazel test //my/test:target --test_arg=--enable_display=false

जीयूआई की जांच करना

अगर $DISPLAY एनवायरमेंट वैरिएबल सेट है, तो इसे चालू किया जा सकता है टेस्ट के दौरान, एम्युलेटर का ग्राफ़िकल इंटरफ़ेस. ऐसा करने के लिए, Baज़र के लिए, ये टेस्ट आर्ग्युमेंट:

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), तो आप नीचे दिए गए स्निपेट का इस्तेमाल करके अपना बेज़ल वर्कस्पेस में, आम तौर पर इस्तेमाल होने वाले Espresso आर्टफ़ैक्ट और उनके dependencies:

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 की जानकारी देनी होगी.
  • अगर किसी लोकल डिवाइस या एम्युलेटर का इस्तेमाल किया जा रहा है, तो Basel, APK के बाद के APK अनइंस्टॉल नहीं करता है का पता लगाना है. इस निर्देश को चलाकर, पैकेज हटाएं:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall