Nếu bạn mới làm quen với Bazel, hãy bắt đầu bằng hướng dẫn Xây dựng Android bằng Bazel.
Hình 1. Chạy các quy trình kiểm thử đo lường Android song song.
android_instrumentation_test
cho phép nhà phát triển kiểm thử ứng dụng của họ trên trình mô phỏng và thiết bị Android.
Nó sử dụng các API khung Android thực và Thư viện kiểm thử Android.
Để đảm bảo tính khép kín và khả năng tái tạo, Bazel tạo và khởi chạy trình mô phỏng Android trong một hộp cát, đảm bảo rằng các kiểm thử luôn chạy ở trạng thái sạch. Mỗi bài kiểm thử sẽ có một phiên bản trình mô phỏng riêng biệt, cho phép các bài kiểm thử chạy song song mà không cần truyền trạng thái giữa chúng.
Để biết thêm thông tin về kiểm thử đo lường Android, hãy xem tài liệu dành cho nhà phát triển Android.
Vui lòng báo cáo vấn đề trong công cụ theo dõi lỗi GitHub.
Cách hoạt động
Khi bạn chạy bazel test
trên mục tiêu android_instrumentation_test
lần đầu tiên, Bazel sẽ thực hiện các bước sau:
- Tạo APK kiểm thử, APK đang kiểm thử và các phần phụ thuộc bắc cầu của chúng
- Tạo, khởi động và lưu vào bộ nhớ đệm các trạng thái trình mô phỏng sạch
- Khởi động trình mô phỏng
- Cài đặt các APK
- Chạy các kiểm thử bằng cách sử dụng Android Test Orchestrator
- Tắt trình mô phỏng
- Báo cáo kết quả
Trong các lần chạy thử nghiệm tiếp theo, Bazel sẽ khởi động trình mô phỏng từ trạng thái sạch, được lưu vào bộ nhớ đệm mà bạn đã tạo ở bước 2, nên sẽ không có trạng thái còn sót lại từ các lần chạy trước. Việc lưu vào bộ nhớ đệm trạng thái trình mô phỏng cũng giúp tăng tốc độ chạy thử.
Điều kiện tiên quyết
Đảm bảo môi trường của bạn đáp ứng các điều kiện tiên quyết sau:
Linux. Đã kiểm thử trên Ubuntu 16.04 và 18.04.
Bazel 0.12.0 trở lên. Xác minh phiên bản bằng cách chạy
bazel info release
.
bazel info release
Kết quả sẽ tương tự như sau:
release 4.1.0
- KVM. Bazel yêu cầu trình mô phỏng phải có tính năng tăng tốc phần cứng bằng KVM trên Linux. Bạn có thể làm theo hướng dẫn cài đặt này cho Ubuntu.
Để xác minh rằng KVM có cấu hình chính xác, hãy chạy:
apt-get install cpu-checker && kvm-ok
Nếu lệnh này in thông báo sau, tức là bạn đã định cấu hình chính xác:
INFO: /dev/kvm exists
KVM acceleration can be used
- Xvfb. Để chạy các kiểm thử không có giao diện người dùng (ví dụ: trên máy chủ CI), Bazel yêu cầu khung hình đệm ảo X.
Để cài đặt, hãy chạy:
apt-get install xvfb
Xác minh rằng Xvfb
được cài đặt đúng cách và được cài đặt tại /usr/bin/Xvfb
bằng cách chạy:
which Xvfb
Kết quả sẽ như sau:
/usr/bin/Xvfb
- Thư viện 32 bit. Một số tệp nhị phân mà cơ sở hạ tầng kiểm thử sử dụng là 32 bit, vì vậy, trên các máy 64 bit, hãy đảm bảo rằng bạn có thể chạy các tệp nhị phân 32 bit. Đối với Ubuntu, hãy cài đặt các thư viện 32 bit sau:
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
Bắt đầu
Sau đây là biểu đồ phụ thuộc mục tiêu điển hình của một android_instrumentation_test
:
Hình 2. Biểu đồ phần phụ thuộc mục tiêu của một android_instrumentation_test
.
Tệp BUILD
Biểu đồ này sẽ chuyển thành một tệp BUILD
như sau:
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",
]
# ...
)
Các thuộc tính chính của quy tắc android_instrumentation_test
là:
test_app
: Một mục tiêuandroid_binary
. Mục tiêu này chứa mã kiểm thử và các phần phụ thuộc như Espresso và UIAutomator.android_binary
mục tiêu đã chọn phải chỉ định một thuộc tínhinstruments
trỏ đến mộtandroid_binary
khác, đó là ứng dụng đang được kiểm thử.target_device
: Một mục tiêuandroid_device
. Mục tiêu này mô tả các thông số kỹ thuật của trình mô phỏng Android mà Bazel dùng để tạo, chạy và thực hiện các kiểm thử. Hãy xem phần về cách chọn thiết bị Android để biết thêm thông tin.
AndroidManifest.xml
của ứng dụng kiểm thử phải có thẻ <instrumentation>
.
Thẻ này phải chỉ định các thuộc tính cho gói của ứng dụng mục tiêu và tên lớp đủ điều kiện của trình chạy kiểm thử đo lường, androidx.test.runner.AndroidJUnitRunner
.
Sau đây là một ví dụ về AndroidTestManifest.xml
cho ứng dụng kiểm thử:
<?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>
Phần phụ thuộc WORKSPACE
Để sử dụng quy tắc này, dự án của bạn cần phụ thuộc vào các kho lưu trữ bên ngoài sau:
@androidsdk
: SDK Android. Tải xuống thông qua Android Studio.@android_test_support
: Lưu trữ trình chạy kiểm thử, trình chạy trình mô phỏng và các mục tiêuandroid_device
. Bạn có thể tìm thấy bản phát hành mới nhất tại đây.
Bật các phần phụ thuộc này bằng cách thêm các dòng sau vào tệp 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()
Phần phụ thuộc Maven
Để quản lý các phần phụ thuộc trên các cấu phần phần mềm Maven từ các kho lưu trữ, chẳng hạn như Google Maven hoặc Maven Central, bạn nên sử dụng một trình phân giải Maven, chẳng hạn như rules_jvm_external
.
Phần còn lại của trang này cho biết cách sử dụng rules_jvm_external
để phân giải và tìm nạp các phần phụ thuộc từ kho lưu trữ Maven.
Chọn mục tiêu android_device
android_instrumentation_test.target_device
chỉ định thiết bị Android để chạy các kiểm thử. Các mục tiêu android_device
này được xác định trong @android_test_support
.
Ví dụ: bạn có thể truy vấn các nguồn cho một mục tiêu cụ thể bằng cách chạy:
bazel query --output=build @android_test_support//tools/android/emulated_devices/generic_phone:android_23_x86
Điều này dẫn đến kết quả đầu ra có dạng như sau:
# .../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",
)
Tên mục tiêu của thiết bị sử dụng mẫu sau:
@android_test_support//tools/android/emulated_devices/device_type :system _api_level _x86_qemu2
Để chạy một android_device
, bạn cần có system_image
cho cấp độ API đã chọn. Để tải hình ảnh hệ thống xuống, hãy sử dụng tools/bin/sdkmanager
của Android SDK. Ví dụ: để tải hình ảnh hệ thống cho generic_phone:android_23_x86
xuống, hãy chạy $sdk/tools/bin/sdkmanager
"system-images;android-23;default;x86"
.
Để xem danh sách đầy đủ các mục tiêu android_device
được hỗ trợ trong @android_test_support
, hãy chạy lệnh sau:
bazel query 'filter("x86_qemu2$", kind(android_device, @android_test_support//tools/android/emulated_devices/...:*))'
Bazel hiện chỉ hỗ trợ trình mô phỏng dựa trên x86. Để có hiệu suất tốt hơn, hãy sử dụng các mục tiêu QEMU2
android_device
thay vì mục tiêu QEMU
.
Chạy kiểm thử
Để chạy các quy trình kiểm thử, hãy thêm những dòng này vào tệp project root:/.bazelrc
của dự án.
# 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
Sau đó, hãy dùng một trong các cấu hình để chạy kiểm thử:
bazel test //my/test:target --config=gui
bazel test //my/test:target --config=headless
bazel test //my/test:target --config=local_device
Chỉ sử dụng một cấu hình hoặc các kiểm thử sẽ không thành công.
Kiểm thử không có giao diện người dùng
Với Xvfb
, bạn có thể kiểm thử bằng trình mô phỏng mà không cần giao diện đồ hoạ, còn được gọi là kiểm thử không cần giao diện người dùng. Để tắt giao diện đồ hoạ khi chạy các bài kiểm thử, hãy truyền đối số kiểm thử --enable_display=false
đến Bazel:
bazel test //my/test:target --test_arg=--enable_display=false
Kiểm thử GUI
Nếu bạn đặt biến môi trường $DISPLAY
, thì bạn có thể bật giao diện đồ hoạ của trình mô phỏng trong khi quá trình kiểm thử đang chạy. Để thực hiện việc này, hãy truyền các đối số kiểm thử này đến Bazel:
bazel test //my/test:target --test_arg=--enable_display=true --test_env=DISPLAY
Kiểm thử bằng trình mô phỏng hoặc thiết bị cục bộ
Bazel cũng hỗ trợ kiểm thử trực tiếp trên trình mô phỏng hoặc thiết bị đã kết nối được khởi chạy cục bộ. Truyền các cờ --test_strategy=exclusive
và --test_arg=--device_broker_type=LOCAL_ADB_SERVER
để bật chế độ kiểm thử cục bộ.
Nếu có nhiều thiết bị được kết nối, hãy truyền cờ --test_arg=--device_serial_number=$device_id
trong đó $device_id
là mã nhận dạng của thiết bị/trình mô phỏng có trong adb devices
.
Dự án mẫu
Nếu bạn đang tìm các mẫu dự án chính tắc, hãy xem các mẫu kiểm thử Android cho các dự án sử dụng Espresso và UIAutomator.
Thiết lập Espresso
Nếu viết các kiểm thử giao diện người dùng bằng Espresso (androidx.test.espresso
), bạn có thể sử dụng các đoạn mã sau để thiết lập không gian làm việc Bazel bằng danh sách các cấu phần phần mềm Espresso thường dùng và các phần phụ thuộc của chúng:
androidx.test.espresso:espresso-core
androidx.test:rules
androidx.test:runner
javax.inject:javax.inject
org.hamcrest:java-hamcrest
junit:junit
Một cách để sắp xếp các phần phụ thuộc này là tạo một thư viện dùng chung //:test_deps
trong tệp 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",
],
)
Sau đó, hãy thêm các phần phụ thuộc bắt buộc vào 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",
],
)
Cuối cùng, trong mục tiêu kiểm thử android_binary
, hãy thêm phần phụ thuộc //:test_deps
:
android_binary(
name = "my_test_app",
instruments = "//path/to:app",
deps = [
"//:test_deps",
# ...
],
# ...
)
Mẹo
Đọc nhật ký kiểm thử
Sử dụng --test_output=errors
để in nhật ký cho các bài kiểm thử không đạt hoặc --test_output=all
để in tất cả kết quả kiểm thử. Nếu bạn đang tìm nhật ký kiểm thử riêng lẻ, hãy chuyển đến $PROJECT_ROOT/bazel-testlogs/path/to/InstrumentationTestTargetName
.
Ví dụ: nhật ký kiểm thử cho dự án chính tắc BasicSample
nằm trong bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
, hãy chạy:
tree bazel-testlogs/ui/espresso/BasicSample/BasicSampleInstrumentationTest
Điều này dẫn đến kết quả sau:
$ 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
Đọc nhật ký trình mô phỏng
Nhật ký trình mô phỏng cho các mục tiêu android_device
được lưu trữ trong thư mục /tmp/
có tên emulator_xxxxx.log
, trong đó xxxxx
là một chuỗi ký tự được tạo ngẫu nhiên.
Sử dụng lệnh này để tìm nhật ký trình mô phỏng mới nhất:
ls -1t /tmp/emulator_*.log | head -n 1
Kiểm thử với nhiều cấp độ API
Nếu muốn kiểm thử với nhiều cấp độ API, bạn có thể dùng một danh sách để tạo các mục tiêu kiểm thử cho từng cấp độ API. Ví dụ:
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]
Vấn đề đã biết
- Các quy trình máy chủ adb được phân nhánh sẽ không bị chấm dứt sau khi kiểm thử
- Mặc dù quá trình tạo APK hoạt động trên mọi nền tảng (Linux, macOS, Windows), nhưng quá trình kiểm thử chỉ hoạt động trên Linux.
- Ngay cả khi có
--config=local_adb
, người dùng vẫn cần chỉ địnhandroid_instrumentation_test.target_device
. - Nếu sử dụng thiết bị hoặc trình mô phỏng cục bộ, Bazel sẽ không gỡ cài đặt các APK sau khi kiểm thử. Xoá các gói bằng cách chạy lệnh sau:
adb shell pm list
packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs
-L1 -t adb uninstall