Espresso — khái niệm, nguyên lý hoạt động và cách sử dụng

Tác giả: IT Sectr Đã đăng: 2026-04-08 Thời gian đọc: 8 phút

Espresso là framework kiểm thử UI tự động cho các ứng dụng Android, được phát triển bởi nhóm Google và là một phần của AndroidX Test. Không giống như kiểm thử công cụ kiểm tra các thành phần riêng lẻ, Espresso tương tác với UI thực: nhấp nút, nhập văn bản, kiểm tra hiển thị phần tử. Theo Google Android Developers, Espresso cung cấp đồng bộ tự động với luồng UI, loại bỏ nhu cầu sử dụng Thread.sleep() thủ công.

Những điểm chính

  • Espresso — framework kiểm thử UI Android với đồng bộ luồng tự động.
  • ViewMatcher — xác định vị trí phần tử View trên màn hình theo ID, văn bản hoặc hệ phân cấp cha.
  • ViewAction — thực hiện hành động trên phần tử: nhấp, nhập văn bản, vuốt.
  • ViewAssertion — kiểm tra trạng thái phần tử: hiển thị, chứa văn bản, hoạt động.
  • Idling Resource — cơ chế chờ hoàn thành các thao tác bất đồng bộ trước khi kiểm tra UI.

Espresso là gì?

Espresso là thư viện viết kiểm thử UI tự động cho Android, một phần của Google AndroidX Test. Nó cung cấp API để tìm phần tử View trên màn hình, thực hiện hành động trên chúng (nhấp, nhập, vuốt) và kiểm tra trạng thái của chúng (hiển thị, chứa văn bản, được kích hoạt).

Tính năng chính của Espresso là đồng bộ tự động với luồng chính của ứng dụng. Framework chờ tất cả các tác vụ bất đồng bộ (coroutine, AsyncTask, Handler) hoàn thành trước khi thực hiện kiểm tra tiếp theo. Điều này loại bỏ các kiểm thử không ổn định do điều kiện cạnh tranh và làm cho kiểm thử UI ổn định và đáng tin cậy — không kiểm thử nào chứa Thread.sleep() hoặc vòng lặp chờ.

Espresso tuân theo nguyên tắc Chó Ba Chân — một kiểm thử gồm ba bước: tìm phần tử (ViewMatcher), thực hiện hành động (ViewAction), kiểm tra kết quả (ViewAssertion). Cả ba bước được viết trong một chuỗi gọi: onView().perform().check(). Khái niệm này làm cho kiểm thử dễ dự đoán và dễ đọc — mỗi kiểm thử mô tả rõ ràng nó tìm gì, làm gì và kiểm tra gì.

Cách Espresso hoạt động

Kiến trúc của Espresso dựa trên ba thành phần: Espresso (điểm vào — phương thức tĩnh onView và onData), ViewMatchers (tìm kiếm phần tử), ViewActions (hành động) và ViewAssertions (kiểm tra). Bên trong, framework sử dụng Idling Resource để đồng bộ với luồng UI.

Kiểm thử Espresso cơ bản

Kiểm thử đơn giản nhất tìm nút theo ID, thực hiện nhấp và kiểm tra văn bản “Hoàn tất” xuất hiện. Tất cả thao tác đều đồng bộ từ góc nhìn kiểm thử — Espresso đảm bảo luồng UI đã xử lý xong sự kiện trước khi kiểm thử tiếp tục. Điều này đạt được nhờ cơ chế chờ tích hợp: onView chặn thực thi kiểm thử cho đến khi UI ở trạng thái rảnh.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // Tìm nút theo ID và nhấp
    onView(withId(R.id.button_submit))
        .perform(click())

    // Kiểm tra văn bản “Hoàn tất” được hiển thị
    onView(withText("Hoàn tất"))
        .check(matches(isDisplayed()))
}

Quy tắc ActivityScenario

Để khởi chạy kiểm thử Espresso, ActivityScenario (AndroidX Test) được sử dụng, tạo một Activity ở trạng thái cụ thể — đang chạy, tạm dừng hoặc bị hủy. ActivityScenario cho phép kiểm tra vòng đời Activity ngoài kiểm thử UI thuần túy. Ví dụ, bạn có thể kiểm tra dữ liệu được bảo toàn khi xoay màn hình (tái tạo Activity) và được khôi phục sau khi hủy.

ViewMatchers là tập hợp các phương thức từ lớp Espresso.onView cho phép tìm Views trên màn hình theo nhiều tiêu chí: ID tài nguyên (R.id), văn bản, gợi ý, phần tử cha và hệ phân cấp. Nếu một matcher không cho kết quả duy nhất, các matcher có thể được kết hợp bằng allOf().

MatcherMục đích
withId(R.id.name)Tìm theo ID tài nguyên
withText(“văn bản”)Tìm theo văn bản hiển thị
withHint(“gợi ý”)Tìm theo thuộc tính gợi ý của EditText
isDisplayed()Kiểm tra phần tử hiển thị trên màn hình
hasSibling(matcher)Tìm theo phần tử anh em
allOf(m1, m2)Kết hợp nhiều matcher

Kết hợp matcher

Nếu có nhiều phần tử giống nhau trên màn hình (ví dụ, hai TextView với văn bản khác nhau), có thể kết hợp matcher bằng allOf: onView(allOf(withId(R.id.title), withText(“Xin chào”))). Điều này đảm bảo chọn một phần tử duy nhất. Toán tử nghịch đảo — not() — loại trừ phần tử khỏi tìm kiếm, và hasSibling() tìm phần tử bên cạnh phần tử đã biết.

ViewActions: tương tác với UI

ViewActions là các hành động Espresso thực hiện trên View tìm được: click(), typeText(), clearText(), scrollTo(), swipeLeft() và các hành động khác. Các hành động được truyền vào phương thức perform(), có thể chấp nhận nhiều hành động liên tiếp.

Chuỗi hành động

Phương thức perform() chấp nhận vararg ViewAction, cho phép thực hiện chuỗi hành động trên một phần tử: xóa trường, nhập văn bản mới, đóng bàn phím và nhấp nút. Tất cả hành động thực hiện theo thứ tự liệt kê, và Espresso đảm bảo hành động trước hoàn thành trước khi hành động tiếp theo bắt đầu.

kotlin
// Nhập văn bản vào EditText và nhấp nút
onView(withId(R.id.edit_email))
    .perform(
        clearText(),
        typeText("user@example.com"),
        closeSoftKeyboard()
    )

onView(withId(R.id.button_login))
    .perform(click())

Kiểm tra qua onData

Đối với phần tử bên trong AdapterView (ListView, RecyclerView), phương thức onData() được sử dụng thay vì onView. Nó làm việc với dữ liệu adapter thay vì Views — tìm phần tử theo nội dung model và trả về View tương ứng cho các hành động tiếp theo. onData sử dụng matcher hamcrest để xác định vị trí phần tử theo trường dữ liệu model.

ViewAssertions: kiểm tra trạng thái

ViewAssertions kiểm tra View ở trạng thái cụ thể. Phương thức cơ bản — matches(matcher) — kiểm tra phần tử khớp với matcher đã cho. Ngoài ra, Espresso cung cấp doesNotExist() (phần tử không tồn tại) và selectedDescendantsMatch() (kiểm tra phần tử lồng nhau).

Kiểm tra điển hình

Các kiểm tra phổ biến nhất trong kiểm thử UI: phần tử hiển thị (isDisplayed), phần tử chứa văn bản cụ thể (withText), phần tử được kích hoạt (isEnabled), phần tử không được chọn (isNotChecked). Mỗi kiểm tra ném ngoại lệ chi tiết khi thất bại — bao gồm hệ phân cấp View trên màn hình. Điều này đơn giản hóa việc gỡ lỗi: thông báo lỗi hiển thị phần tử nào thực sự có trên màn hình tại thời điểm kiểm tra.

ViewAssertions tùy chỉnh

Nếu kiểm tra tiêu chuẩn không đủ, có thể tạo kiểm tra tùy chỉnh qua giao diện ViewAssertion. Một assertion tùy chỉnh nhận View và có thể kiểm tra trạng thái của nó theo chương trình — ví dụ, màu văn bản, đệm hoặc trạng thái của thành phần tùy chỉnh không được hiển thị qua matcher tiêu chuẩn.

kotlin
// Kiểm tra: TextView hiển thị và chứa văn bản
onView(withId(R.id.text_welcome))
    .check(matches(isDisplayed()))
    .check(matches(withText("Chào mừng")))

// Kiểm tra: phần tử KHÔNG hiển thị
onView(withId(R.id.progress_bar))
    .check(doesNotExist())

Idling Resources cho thao tác bất đồng bộ

Idling Resource là cơ chế của Espresso để đồng bộ kiểm thử với các thao tác bất đồng bộ. Theo mặc định, Espresso chờ Handler, AsyncTask và coroutine (qua coroutinesIdlingResource). Nếu ứng dụng thực hiện công việc nền qua luồng tùy chỉnh hoặc dịch vụ callback, cần đăng ký Idling Resource tùy chỉnh.

Ví dụ với coroutine

Từ AndroidX Test 1.4.0, Espresso hỗ trợ coroutine qua CoroutinesIdlingResource. Kiểm thử tự động chờ tất cả coroutine đã khởi chạy hoàn thành trước khi thực hiện kiểm tra UI. Đối với kịch bản phức tạp hơn, CountingIdlingResource được sử dụng — bộ đếm tăng khi bắt đầu tác vụ và giảm khi hoàn thành.

kotlin
// Đăng ký IdlingResource cho OkHttp
class OkHttpIdlingResource(
    private val client: OkHttpClient
) : IdlingResource {

    private var isIdle = true
    private var watcher: IdlingResource.ResourceCallback? = null

    override fun getName() = "OkHttp"

    override fun isIdleNow() = isIdle

    override fun registerIdleTransitionCallback(
        callback: IdlingResource.ResourceCallback
    ) {
        watcher = callback
    }
}

Thiết lập Espresso trong dự án Android

Kết nối Espresso vào dự án Android được thực hiện bằng cách thêm phụ thuộc vào build.gradle cấp module. Espresso là một phần của AndroidX Test, vì vậy chỉ cần chỉ định phụ thuộc cho lõi Espresso, tiện ích mở rộng và tích hợp JUnit. Kiểm thử được đặt trong thư mục src/androidTest và chạy trên thiết bị vật lý hoặc giả lập qua AndroidJUnitRunner.

Cấu hình Gradle

Tập phụ thuộc tối thiểu bao gồm espresso-core (lõi), espresso-contrib (matcher bổ sung cho RecyclerView, Drawer, Picker) và runner (trình chạy kiểm thử AndroidX). Tất cả kiểm thử chạy trên giả lập hoặc thiết bị vật lý qua Android Test Orchestrator.

kotlin
// build.gradle.kts (phụ thuộc androidTest)
android {
    defaultConfig {
        testInstrumentationRunner =
            "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
    androidTestImplementation("androidx.test.espresso:espresso-contrib:3.6.1")
    androidTestImplementation("androidx.test:runner:1.6.1")
    androidTestImplementation("androidx.test:rules:1.6.1")
}

Chạy kiểm thử trên CI

Kiểm thử Espresso có thể chạy qua Google Android Test Orchestrator, cách ly mỗi kiểm thử trong một tiến trình riêng và xóa trạng thái giữa các lần chạy. Điều này loại bỏ kiểm thử không ổn định do dữ liệu còn sót từ kiểm thử trước và cải thiện độ ổn định trên máy chủ CI. Để thực thi song song, sharding được sử dụng — phân phối kiểm thử giữa nhiều giả lập.

Câu hỏi thường gặp

Espresso khác UI Automator như thế nào?

Espresso hoạt động bên trong tiến trình ứng dụng và sử dụng đồng bộ tự động với luồng UI. UI Automator hoạt động ở cấp hệ thống, có thể tương tác với ứng dụng khác, nhưng yêu cầu quản lý chờ thủ công.

Tại sao Espresso được gọi là framework “chó ba chân”?

Đây là phép ẩn dụ từ bài thuyết trình của Google: kiểm thử Espresso đứng trên ba trụ cột — ViewMatcher (tìm), ViewAction(hành động) và ViewAssertion(kiểm tra). Bỏ bất kỳ cột nào, kiểm thử mất ổn định, như con chó ba chân.

Làm thế nào để kiểm tra RecyclerView qua Espresso?

Đối với RecyclerView, thư viện espresso-contrib được sử dụng với các phương thức như onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())). Thay thế là onData() cho AdapterView hoặc ViewAction tùy chỉnh để tìm phần tử theo văn bản trong RecyclerView. Ngoài ra, RecyclerViewActions từ espresso-contrib có thể được dùng để cuộn đến phần tử và thực hiện hành động trên đó.

Kiểm thử không ổn định (flaky) là gì và Espresso xử lý thế nào?

Kiểm thử không ổn định là kiểm thử đôi khi thất bại mà không thay đổi mã, do điều kiện cạnh tranh hoặc bất đồng bộ. Espresso giải quyết vấn đề này bằng Idling Resource — chờ tất cả tác vụ nền hoàn thành trước khi thực hiện kiểm tra.

Có thể sử dụng Espresso cho kiểm thử ảnh chụp màn hình không?

Bản thân Espresso không được thiết kế cho kiểm thử ảnh chụp màn hình, nhưng có thể kết hợp với các thư viện như Shot hoặc Paparazzi. Espresso chuẩn bị UI ở trạng thái mong muốn, và thư viện so sánh chụp ảnh màn hình và so sánh với tham chiếu. Cách tiếp cận này gọi là kiểm thử hồi quy trực quan và giúp tìm các thay đổi không mong đợi trong giao diện.

Tổng kết

  • Espresso — framework kiểm thử UI Android của Google với đồng bộ tự động.
  • ViewMatchers — API tìm phần tử theo ID, văn bản, hệ phân cấp và kết hợp.
  • ViewActions — click, typeText, scrollTo, swipe để tương tác UI.
  • ViewAssertions — matches, doesNotExist để kiểm tra trạng thái phần tử.
  • Idling Resource — đồng bộ kiểm thử với thao tác bất đồng bộ và coroutine.
  • Ba bước — onView().perform().check() = tìm, thực hiện, kiểm tra.
  • AndroidX Test — thư viện chạy kiểm thử công cụ trên giả lập hoặc thiết bị.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm