Espresso — چیست، اصول کار و نحوه استفاده

نویسنده: IT Sectr منتشر شده: 2026-04-08 زمان مطالعه: 8 دقیقه

Espresso یک فریم‌ورک برای تست خودکار UI برنامه‌های Android است که توسط تیم Google توسعه یافته و بخشی از AndroidX Test می‌باشد. برخلاف تست‌های ابزاری که کامپوننت‌های ایزوله را بررسی می‌کنند، Espresso با UI واقعی تعامل دارد: دکمه‌ها را فشار می‌دهد، متن وارد می‌کند، نمایش عناصر را بررسی می‌کند. به گفته Google Android Developers، Espresso همگام‌سازی خودکار با رشته UI را فراهم می‌کند که نیاز به Thread.sleep() دستی را از بین می‌برد.

نکات اصلی

  • Espresso — فریم‌ورک تست UI Android با همگام‌سازی خودکار رشته‌ها.
  • ViewMatcher — جستجوی عنصر View در صفحه بر اساس ID، متن، سلسله‌مراتب والد.
  • ViewAction — عمل روی عنصر: کلیک، ورود متن، سوایپ.
  • ViewAssertion — بررسی وضعیت عنصر: نمایش داده می‌شود، شامل متن است، فعال است.
  • Idling Resource — مکانیزم انتظار برای تکمیل عملیات ناهمگام قبل از بررسی UI.

Espresso چیست؟

Espresso یک کتابخانه برای نوشتن تست‌های UI خودکار Android است که بخشی از Google AndroidX Test می‌باشد. این کتابخانه APIهایی برای جستجوی عناصر View در صفحه، انجام اقدامات روی آنها (کلیک، ورود، سوایپ) و بررسی وضعیت آنها (نمایش داده می‌شود، شامل متن است، فعال است) ارائه می‌دهد.

ویژگی کلیدی Espresso — همگام‌سازی خودکار با رشته اصلی برنامه است. فریم‌ورک منتظر تکمیل تمام وظایف ناهمگام (کروتین‌ها، AsyncTask، Handler) قبل از انجام بررسی بعدی می‌ماند. این کار تست‌های ناپایدار مرتبط با race condition را حذف کرده و تست‌های UI را پایدار و قابل اعتماد می‌سازد — هیچ تستی شامل Thread.sleep() یا حلقه‌های انتظار نیست.

Espresso از اصل Three-Legged Dog پیروی می‌کند — تست از سه مرحله تشکیل شده است: یافتن عنصر (ViewMatcher)، انجام عمل (ViewAction)، بررسی نتیجه (ViewAssertion). هر سه مرحله در زنجیره فراخوانی onView().perform().check() نوشته می‌شوند. این مفهوم تست‌ها را قابل پیش‌بینی و خوانا می‌سازد — هر تست به وضوح توضیح می‌دهد که چه چیزی را جستجو می‌کند، چه کاری انجام می‌دهد و چه چیزی را بررسی می‌کند.

Espresso چگونه کار می‌کند

معماری Espresso بر سه مؤلفه استوار است: Espresso (نقطه ورود — متدهای استاتیک onView و onData)، ViewMatchers (جستجوی عناصر)، ViewActions (اقدامات) و ViewAssertions (بررسی‌ها). در داخل، فریم‌ورک از Idling Resource برای همگام‌سازی با رشته UI استفاده می‌کند.

تست پایه Espresso

یک تست ساده دکمه‌ای را با ID پیدا می‌کند، کلیک را انجام می‌دهد و بررسی می‌کند که متن «تمام» ظاهر شده است. تمام عملیات از دید تست به صورت همزمان انجام می‌شود — Espresso تضمین می‌کند که رشته UI پردازش رویداد را قبل از ادامه تست به پایان رسانده است. این کار از طریق مکانیزم انتظار داخلی به دست می‌آید: onView اجرای تست را مسدود می‌کند تا زمانی که UI پایدار شود.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // یافتن دکمه با شناسه و کلیک کردن
    onView(withId(R.id.button_submit))
        .perform(click())

    // بررسی اینکه متن «تمام» نمایش داده می‌شود
    onView(withText("تمام"))
        .check(matches(isDisplayed()))
}

قانون ActivityScenario

برای راه‌اندازی تست Espresso از ActivityScenario (AndroidX Test) استفاده می‌شود که Activity را در وضعیت مورد نظر ایجاد می‌کند — در حال اجرا، متوقف شده، نابود شده. ActivityScenario امکان تست چرخه حیات Activity را علاوه بر UI خالص فراهم می‌کند. به عنوان مثال، می‌توان بررسی کرد که داده‌ها در چرخش صفحه (بازآفرینی Activity) ذخیره شده و پس از نابودی بازیابی می‌شوند.

ViewMatchers مجموعه‌ای از متدهای کلاس Espresso.onView هستند که امکان یافتن View در صفحه را بر اساس معیارهای مختلف فراهم می‌کنند: شناسه منبع (R.id)، متن، راهنمای hint، عنصر والد و سلسله‌مراتب. اگر یک matcher نتیجه منحصربه‌فرد ندهد، matcherها از طریق allOf() ترکیب می‌شوند.

Matcherکاربرد
withId(R.id.name)جستجو بر اساس ID منبع
withText("متن")جستجو بر اساس متن نمایش داده شده
withHint("راهنما")جستجو بر اساس ویژگی hint در EditText
isDisplayed()بررسی نمایش عنصر در صفحه
hasSibling(matcher)جستجو بر اساس عنصر مجاور
allOf(m1, m2)ترکیب چند matcher

ترکیب matcherها

اگر چندین عنصر مشابه در صفحه وجود داشته باشد (مثلاً دو TextView با متن‌های مختلف)، ترکیب matcherها از طریق allOf很方便 است: onView(allOf(withId(R.id.title), withText("سلام"))). این کار انتخاب یک عنصر واحد را تضمین می‌کند. عملگر معکوس — not() — عناصر را از جستجو حذف می‌کند و hasSibling() عنصر را در کنار عنصر شناخته شده جستجو می‌کند.

ViewActions: تعامل با UI

ViewActions اقداماتی هستند که Espresso روی View یافت شده انجام می‌دهد: click()، typeText()، clearText()، scrollTo()، swipeLeft() و موارد دیگر. اقدامات به متد perform() منتقل می‌شوند که می‌تواند چندین عمل را پشت سر هم بپذیرد.

زنجیره اقدامات

متد perform() vararg ViewAction را می‌پذیرد که امکان اجرای دنباله‌ای از اقدامات روی یک عنصر را فراهم می‌کند: پاک کردن فیلد، وارد کردن متن جدید، بستن صفحه‌کلید و کلیک دکمه. تمام اقدامات به ترتیب ذکر شده انجام می‌شوند و Espresso تضمین می‌کند که عمل قبلی قبل از شروع عمل بعدی کامل شده است.

kotlin
// ورود متن در EditText و کلیک دکمه
onView(withId(R.id.edit_email))
    .perform(
        clearText(),
        typeText("user@example.com"),
        closeSoftKeyboard()
    )

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

بررسی از طریق onData

برای عناصر داخل AdapterView (ListView, RecyclerView) از متد onData() به جای onView استفاده می‌شود. این متد با داده‌های آداپتر کار می‌کند نه با View — عنصر را بر اساس محتوای مدل پیدا می‌کند و View مربوطه را برای اقدامات بعدی برمی‌گرداند. onData از matcherهای hamcrest برای جستجوی عنصر بر اساس فیلدهای مدل داده استفاده می‌کند.

ViewAssertions: بررسی وضعیت

ViewAssertions بررسی می‌کنند که View در وضعیت مشخصی قرار دارد. متد پایه — matches(matcher) — بررسی می‌کند که عنصر با matcher داده شده مطابقت دارد. علاوه بر این، Espresso doesNotExist() (عنصر وجود ندارد) و selectedDescendantsMatch() (بررسی عناصر تو در تو) را ارائه می‌دهد.

بررسی‌های معمول

رایج‌ترین بررسی‌ها در تست‌های UI: عنصر نمایش داده می‌شود (isDisplayed)، عنصر شامل متن مشخصی است (withText)، عنصر فعال است (isEnabled)، عنصر انتخاب نشده است (isNotChecked). هر بررسی در صورت شکست یک استثنای دقیق با ذکر سلسله‌مراتب View در صفحه ایجاد می‌کند. این کار اشکال‌زدایی را ساده می‌کند: در پیام خطا مشخص است که چه عناصری واقعاً در لحظه بررسی در صفحه بوده‌اند.

ViewAssertions سفارشی

اگر بررسی‌های استاندارد کافی نباشند، می‌توان از طریق رابط ViewAssertion یک بررسی سفارشی ایجاد کرد. assertion سفارشی View را دریافت کرده و می‌تواند وضعیت آن را برنامه‌نویسی بررسی کند — مثلاً رنگ متن، حاشیه‌ها یا وضعیت کامپوننت سفارشی که از طریق matcherهای استاندارد قابل دسترسی نیست.

kotlin
// بررسی: TextView نمایش داده می‌شود و شامل متن است
onView(withId(R.id.text_welcome))
    .check(matches(isDisplayed()))
    .check(matches(withText("خوش آمدید")))

// بررسی: عنصر نمایش داده نمی‌شود
onView(withId(R.id.progress_bar))
    .check(doesNotExist())

Idling Resources برای عملیات ناهمگام

Idling Resource مکانیزم Espresso برای همگام‌سازی تست با عملیات ناهمگام است. به طور پیش‌فرض، Espresso منتظر تکمیل Handler، AsyncTask و کروتین‌ها (از طریق coroutinesIdlingResource) می‌ماند. اگر برنامه کار پس‌زمینه‌ای را از طریق رشته‌های خود یا سرویس‌های Callback انجام می‌دهد، باید یک Idling Resource سفارشی ثبت کرد.

مثال با کروتین‌ها

از AndroidX Test 1.4.0 به بعد، Espresso از کروتین‌ها از طریق CoroutinesIdlingResource پشتیبانی می‌کند. تست به طور خودکار منتظر تکمیل تمام کروتین‌های راه‌اندازی شده قبل از انجام بررسی‌های UI می‌ماند. برای سناریوهای پیچیده‌تر از CountingIdlingResource استفاده می‌شود — شمارنده‌ای که در شروع کار افزایش و در پایان کاهش می‌یابد.

kotlin
// ثبت IdlingResource برای 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
    }
}

تنظیم Espresso در پروژه Android

اتصال Espresso در پروژه Android از طریق افزودن وابستگی‌ها در build.gradle سطح ماژول انجام می‌شود. Espresso بخشی از AndroidX Test است، بنابراین کافی است وابستگی‌های هسته Espresso، افزونه‌ها و یکپارچه‌سازی JUnit را مشخص کنید. تست‌ها در دایرکتوری src/androidTest قرار می‌گیرند و روی دستگاه فیزیکی یا شبیه‌ساز از طریق AndroidJUnitRunner اجرا می‌شوند.

تنظیمات Gradle

حداقل مجموعه وابستگی‌ها شامل espresso-core (هسته)، espresso-contrib (matcherهای اضافی برای RecyclerView، Drawer، Picker) و runner (رunner تست AndroidX) است. تمام تست‌ها روی شبیه‌ساز یا دستگاه فیزیکی از طریق Android Test Orchestrator اجرا می‌شوند.

kotlin
// build.gradle.kts (androidTest dependencies)
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")
}

اجرای تست‌ها روی CI

تست‌های Espresso را می‌توان از طریق Google Android Test Orchestrator اجرا کرد که هر تست را در یک فرآیند جداگانه ایزوله کرده و وضعیت را بین اجراها پاک می‌کند. این کار تست‌های ناپایدار مرتبط با داده‌های باقی‌مانده از تست‌های قبلی را حذف کرده و پایداری را در سرورهای CI افزایش می‌دهد. برای اجرای موازی از sharding استفاده می‌شود — توزیع تست‌ها بین چند شبیه‌ساز.

سوالات متداول

تفاوت Espresso با UI Automator چیست؟

Espresso در داخل فرآیند برنامه کار می‌کند و از همگام‌سازی خودکار با رشته UI استفاده می‌کند. UI Automator در سطح سیستم کار می‌کند، می‌تواند با برنامه‌های دیگر تعامل داشته باشد، اما نیاز به مدیریت دستی انتظار دارد.

چرا Espresso را فریم‌ورک «سگ سه‌پا» می‌نامند؟

این یک استعاره از ارائه Google است: تست Espresso روی سه پایه ایستاده است — ViewMatcher (جستجو)، ViewAction(عمل) و ViewAssertion(بررسی). اگر هر یک از آنها حذف شود، تست ثبات خود را از دست می‌دهد، مانند یک سگ سه‌پا.

چگونه RecyclerView را با Espresso تست کنیم؟

برای RecyclerView از کتابخانه espresso-contrib و متدهای onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())) استفاده می‌شود. جایگزین — onData() برای AdapterView یا ViewAction سفارشی برای جستجوی عنصر بر اساس متن داخل RecyclerView. علاوه بر این می‌توان از RecyclerViewActions از espresso-contrib برای اسکرول به عنصر و اقدامات روی آن استفاده کرد.

تست ناپایدار (flaky) چیست و Espresso چگونه با آن مقابله می‌کند؟

تست ناپایدار (flaky) تستی است که گاهی بدون تغییر کode، به دلیل race condition یا ناهمگامی، شکست می‌خورد. Espresso این مشکل را از طریق Idling Resource حل می‌کند — انتظار برای تکمیل تمام وظایف پس‌زمینه قبل از انجام بررسی.

آیا می‌توان از Espresso برای تست اسکرین‌شات استفاده کرد؟

خود Espresso برای تست‌های اسکرین‌شات طراحی نشده است، اما می‌توان آن را با کتابخانه‌هایی مانند Shot یا Paparazzi ترکیب کرد. Espresso UI را به وضعیت مورد نظر می‌رساند و کتابخانه مقایسه اسکرین‌شات گرفته و با مرجع مقایسه می‌کند. این رویکرد تست رگرسیون بصری نامیده می‌شود و به یافتن تغییرات غیرمنتظره در رابط کاربری کمک می‌کند.

خلاصه

  • Espresso — فریم‌ورک تست UI Android از Google با همگام‌سازی خودکار.
  • ViewMatchers — API برای جستجوی عناصر بر اساس ID، متن، سلسله‌مراتب و ترکیب‌ها.
  • ViewActions — click, typeText, scrollTo, swipe برای تعامل با UI.
  • ViewAssertions — matches, doesNotExist برای بررسی وضعیت عناصر.
  • Idling Resource — همگام‌سازی تست با عملیات ناهمگام و کروتین‌ها.
  • سه مرحله — onView().perform().check() = پیدا کن، انجام بده، بررسی کن.
  • AndroidX Test — کتابخانه‌های اجرای تست‌های ابزاری روی شبیه‌ساز یا دستگاه.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید