অ্যান্ড্রয়েড ইন্সট্রুমেন্টেশন টেস্ট

আপনি যদি Bazel-এ নতুন হয়ে থাকেন, তাহলে Building Android with Bazel টিউটোরিয়াল দিয়ে শুরু করুন।

Running Android instrumentation tests in parallel

চিত্র 1. সমান্তরাল অ্যান্ড্রয়েড ইন্সট্রুমেন্টেশন পরীক্ষা চলছে।

android_instrumentation_test ডেভেলপারদের Android এমুলেটর এবং ডিভাইসে তাদের অ্যাপ পরীক্ষা করতে দেয়। এটি বাস্তব অ্যান্ড্রয়েড ফ্রেমওয়ার্ক API এবং অ্যান্ড্রয়েড টেস্ট লাইব্রেরি ব্যবহার করে।

হারমেটিসিটি এবং প্রজননযোগ্যতার জন্য, Bazel একটি স্যান্ডবক্সে অ্যান্ড্রয়েড এমুলেটর তৈরি এবং লঞ্চ করে, যাতে পরীক্ষাগুলি সর্বদা একটি পরিষ্কার অবস্থা থেকে চলে তা নিশ্চিত করে। প্রতিটি পরীক্ষায় একটি বিচ্ছিন্ন এমুলেটর দৃষ্টান্ত পাওয়া যায়, যা পরীক্ষাগুলিকে তাদের মধ্যে থাকা অবস্থাগুলি না দিয়ে সমান্তরালভাবে চালানোর অনুমতি দেয়।

অ্যান্ড্রয়েড ইন্সট্রুমেন্টেশন পরীক্ষা সম্পর্কে আরও তথ্যের জন্য, অ্যান্ড্রয়েড ডেভেলপার ডকুমেন্টেশন দেখুন।

অনুগ্রহ করে গিটহাব ইস্যু ট্র্যাকারে সমস্যাগুলি ফাইল করুন।

কিভাবে এটা কাজ করে

আপনি যখন প্রথমবার একটি android_instrumentation_test লক্ষ্যে bazel test চালান, তখন Bazel নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করে:

  1. পরীক্ষার APK, পরীক্ষার অধীনে APK এবং তাদের ট্রানজিটিভ নির্ভরতা তৈরি করে
  2. ক্লিন এমুলেটর স্টেট তৈরি করে, বুট করে এবং ক্যাশে করে
  3. এমুলেটর শুরু করে
  4. APK গুলি ইনস্টল করে
  5. অ্যান্ড্রয়েড টেস্ট অর্কেস্ট্রেটর ব্যবহার করে পরীক্ষা চালায়
  6. এমুলেটর বন্ধ করে দেয়
  7. ফলাফল রিপোর্ট

পরবর্তী টেস্ট রানে, Bazel এমুলেটরটিকে 2 ধাপে তৈরি করা পরিষ্কার, ক্যাশে করা অবস্থা থেকে বুট করে, তাই আগের রান থেকে কোনো অবশিষ্ট নেই। ক্যাশিং এমুলেটর স্টেটও টেস্ট রানের গতি বাড়ায়।

পূর্বশর্ত

আপনার পরিবেশ নিম্নলিখিত পূর্বশর্তগুলি পূরণ করে তা নিশ্চিত করুন:

  • লিনাক্স । উবুন্টু 16.04, এবং 18.04 এ পরীক্ষা করা হয়েছে।

  • Bazel 0.12.0 বা তার পরে। bazel info release চালিয়ে সংস্করণটি যাচাই করুন।

bazel info release

এর ফলে নিম্নলিখিতগুলির মতো আউটপুট পাওয়া যায়:

release 4.1.0

KVM-এর সঠিক কনফিগারেশন আছে তা যাচাই করতে, চালান:

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-বিট বাইনারি চালানো যেতে পারে। উবুন্টুর জন্য, এই 32-বিট লাইব্রেরিগুলি ইনস্টল করুন:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386

শুরু হচ্ছে

এখানে একটি android_instrumentation_test এর একটি সাধারণ লক্ষ্য নির্ভরতা গ্রাফ রয়েছে:

The target dependency graph on an Android instrumentation test

চিত্র 2. একটি 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 টার্গেটটি অন্য android_binary এর দিকে নির্দেশ করে একটি instruments অ্যাট্রিবিউট উল্লেখ করতে হবে, যেটি অ্যাপটি পরীক্ষাধীন।

  • 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>

ওয়ার্কস্পেস নির্ভরতা

এই নিয়মটি ব্যবহার করার জন্য, আপনার প্রকল্পকে এই বাহ্যিক সংগ্রহস্থলগুলির উপর নির্ভর করতে হবে:

  • @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()

মাভেন নির্ভরতা

Google Maven বা Maven Central এর মতো সংগ্রহস্থল থেকে Maven আর্টিফ্যাক্টের উপর নির্ভরতা পরিচালনার জন্য, আপনার একটি Maven সমাধানকারী ব্যবহার করা উচিত, যেমন 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 চালু করতে, নির্বাচিত API স্তরের জন্য 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_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 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 ( androidx.test.espresso ) দিয়ে UI পরীক্ষা লেখেন, তাহলে আপনি সাধারণত ব্যবহৃত 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 স্তরের বিরুদ্ধে পরীক্ষা করা হচ্ছে

আপনি যদি একাধিক 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]

জ্ঞাত সমস্যা

  • ফর্কড এডিবি সার্ভার প্রক্রিয়া পরীক্ষার পরে সমাপ্ত হয় না
  • যদিও APK বিল্ডিং সমস্ত প্ল্যাটফর্মে কাজ করে (লিনাক্স, ম্যাকওএস, উইন্ডোজ), টেস্টিং শুধুমাত্র লিনাক্সে কাজ করে।
  • এমনকি --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