Espresso — ما هو، مبادئ العمل وكيفية الاستخدام

المؤلف: IT Sectr نُشر: 2026-04-08 وقت القراءة: 8 دق

Espresso هو إطار عمل لاختبار واجهة المستخدم الآلي لتطبيقات Android، طورته فريق Google وهو جزء من AndroidX Test. على عكس الاختبارات الآلية التي تتحقق من المكونات المعزولة، يتفاعل Espresso مع واجهة المستخدم الحقيقية: ينقر على الأزرار، يدخل النص، ويتحقق من عرض العناصر. وفقًا لـ Google Android Developers، يوفر Espresso مزامنة تلقائية مع سلسلة واجهة المستخدم، مما يلغي الحاجة إلى Thread.sleep() اليدوي.

الخلاصة

  • Espresso — إطار اختبار واجهة مستخدم Android مع مزامنة تلقائية للسلاسل.
  • ViewMatcher — تحديد موقع عناصر View على الشاشة بواسطة ID أو النص أو التسلسل الهرمي.
  • ViewAction — تنفيذ إجراءات على العنصر: النقر، إدخال النص، التمرير.
  • ViewAssertion — التحقق من حالة العنصر: معروض، يحتوي على نص، نشط.
  • Idling Resource — آلية انتظار اكتمال العمليات غير المتزامنة قبل التحقق من واجهة المستخدم.

ما هو Espresso؟

Espresso هي مكتبة لكتابة اختبارات واجهة مستخدم آلية لـ Android، وهي جزء من Google AndroidX Test. توفر واجهة برمجة تطبيقات للعثور على عناصر View على الشاشة، وتنفيذ إجراءات عليها (نقر، إدخال، تمرير)، والتحقق من حالتها (معروض، يحتوي على نص، ممكّن).

الميزة الرئيسية لـ Espresso هي المزامنة التلقائية مع السلسلة الرئيسية للتطبيق. ينتظر الإطار اكتمال جميع المهام غير المتزامنة (coroutines، AsyncTask، Handler) قبل تنفيذ الفحص التالي. يلغي هذا الاختبارات غير المستقرة الناتجة عن حالات السباق ويجعل اختبارات واجهة المستخدم مستقرة وموثوقة — لا يحتوي أي اختبار على Thread.sleep() أو حلقات انتظار.

يتبع Espresso مبدأ الكلب ذو الثلاث أرجل — يتكون الاختبار من ثلاث خطوات: العثور على عنصر (ViewMatcher)، تنفيذ إجراء (ViewAction)، التحقق من النتيجة (ViewAssertion). تُكتب الخطوات الثلاث في سلسلة استدعاءات: onView().perform().check(). هذا المفهوم يجعل الاختبارات قابلة للتنبؤ وسهلة القراءة — يصف كل اختبار بوضوح ما يبحث عنه، وما يفعله، وما يتحقق منه.

كيف يعمل Espresso

بنية Espresso تعتمد على ثلاثة مكونات: Espresso (نقطة الدخول — الأساليب الثابتة onView و onData)، ViewMatchers (البحث عن العناصر)، ViewActions (الإجراءات) و ViewAssertions (التحقق). داخليًا، يستخدم الإطار Idling Resource للمزامنة مع سلسلة واجهة المستخدم.

اختبار Espresso الأساسي

أبسط اختبار يجد زرًا بواسطة ID، ينقر عليه، ويتحقق من ظهور النص «تم». جميع العمليات متزامنة من منظور الاختبار — يضمن Espresso أن سلسلة واجهة المستخدم قد انتهت من معالجة الحدث قبل أن يستمر الاختبار. يتم تحقيق ذلك من خلال آلية انتظار مدمجة: onView يمنع تنفيذ الاختبار حتى تصبح واجهة المستخدم خاملة.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // البحث عن زر بواسطة ID والنقر
    onView(withId(R.id.button_submit))
        .perform(click())

    // التحقق من عرض النص «تم»
    onView(withText("تم"))
        .check(matches(isDisplayed()))
}

قاعدة ActivityScenario

لإطلاق اختبار Espresso، يُستخدم ActivityScenario (AndroidX Test)، الذي ينشئ Activity في حالة محددة — قيد التشغيل، متوقفة، أو مدمرة. يسمح ActivityScenario باختبار دورة حياة Activity بالإضافة إلى اختبار واجهة المستخدم الخالص. على سبيل المثال، يمكن التحقق من الحفاظ على البيانات عند تدوير الشاشة (إعادة إنشاء Activity) واستعادتها بعد التدمير.

ViewMatchers هي مجموعة من الأساليب من فئة Espresso.onView التي تسمح بالعثور على Views على الشاشة بمعايير مختلفة: ID المورد (R.id)، النص، التلميح، العنصر الأب، والتسلسل الهرمي. إذا لم يعطِ matcher واحد نتيجة فريدة، يمكن دمج matchers باستخدام allOf().

المطابقالغرض
withId(R.id.name)البحث بواسطة ID المورد
withText(«نص»)البحث بواسطة النص المعروض
withHint(«تلميح»)البحث بواسطة خاصية التلميح لـ EditText
isDisplayed()التحقق من أن العنصر مرئي على الشاشة
hasSibling(matcher)البحث بواسطة العنصر المجاور
allOf(m1, m2)دمج عدة مطابقات

دمج المطابقات

إذا كان هناك عدة عناصر متطابقة على الشاشة (مثل TextView بنصوص مختلفة)، فمن المناسب دمج المطابقات باستخدام allOf: onView(allOf(withId(R.id.title), withText(«مرحبًا»))). يضمن ذلك تحديد عنصر واحد. العامل العكسي — not() — يستبعد العناصر من البحث، و hasSibling() يجد عنصرًا بجوار عنصر معروف.

ViewActions: التفاعل مع واجهة المستخدم

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. يعمل مع بيانات المحول بدلاً من Views — يجد عنصرًا بمحتوى النموذج ويعيد View المقابلة لإجراءات إضافية. يستخدم onData مطابقات hamcrest لتحديد موقع عنصر حسب حقول بيانات النموذج.

ViewAssertions: التحقق من الحالة

ViewAssertions تتحقق من أن View في حالة محددة. الطريقة الأساسية — matches(matcher) — تتحقق من تطابق العنصر مع المطابق المحدد. بالإضافة إلى ذلك، يقدم Espresso doesNotExist() (العنصر غير موجود) و selectedDescendantsMatch() (التحقق من العناصر المتداخلة).

التحقق النموذجي

الفحوصات الأكثر شيوعًا في اختبارات واجهة المستخدم: العنصر معروض (isDisplayed)، العنصر يحتوي على نص محدد (withText)، العنصر ممكّن (isEnabled)، العنصر غير محدد (isNotChecked). كل فحص يرمي استثناءً مفصلاً في حالة الفشل — بما في ذلك التسلسل الهرمي للـ Views على الشاشة. هذا يبسط التصحيح: تظهر رسالة الخطأ العناصر التي كانت فعليًا على الشاشة في وقت الفحص.

ViewAssertions مخصصة

إذا كانت الفحوصات القياسية غير كافية، يمكن إنشاء فحص مخصص من خلال واجهة ViewAssertion. التأكيد المخصص يستقبل View ويمكنه التحقق من حالته برمجيًا — على سبيل المثال، لون النص، الهوامش، أو حالة مكون مخصص غير مكشوف من خلال المطابقات القياسية.

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 و coroutines (عبر coroutinesIdlingResource). إذا كان التطبيق يقوم بعمل خلفي من خلال سلاسل مخصصة أو خدمات رد اتصال، يجب تسجيل Idling Resource مخصص.

مثال مع coroutines

بدءًا من AndroidX Test 1.4.0، يدعم Espresso coroutines عبر CoroutinesIdlingResource. ينتظر الاختبار تلقائيًا اكتمال جميع coroutines المُطلقة قبل إجراء فحوصات واجهة المستخدم. للسيناريوهات الأكثر تعقيدًا، يُستخدم 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 (مطابقات إضافية لـ RecyclerView و Drawer و Picker) و runner (مشغل اختبارات AndroidX). تُشغّل جميع الاختبارات على محاكي أو جهاز فعلي عبر Android Test Orchestrator.

kotlin
// build.gradle.kts (تبعيات 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")
}

تشغيل الاختبارات على CI

يمكن تشغيل اختبارات Espresso عبر Google Android Test Orchestrator، الذي يعزل كل اختبار في عملية منفصلة وينظف الحالة بين عمليات التشغيل. يلغي هذا الاختبارات غير المستقرة المرتبطة بالبيانات المتبقية من الاختبارات السابقة ويعزز الاستقرار على خوادم CI. للتشغيل المتوازي، يُستخدم sharding — توزيع الاختبارات بين عدة محاكيات.

الأسئلة الشائعة

ما الفرق بين Espresso و UI Automator؟

Espresso يعمل داخل عملية التطبيق ويستخدم مزامنة تلقائية مع سلسلة واجهة المستخدم. يعمل 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؟

الاختبار غير المستقر — اختبار يفشل أحيانًا دون تغيير في الكود، بسبب حالات السباق أو عدم التزامن. يحل Espresso هذه المشكلة عبر Idling Resource — انتظار اكتمال جميع المهام الخلفية قبل تنفيذ الفحص.

هل يمكن استخدام Espresso لاختبار لقطات الشاشة؟

Espresso نفسه غير مصمم لاختبارات لقطات الشاشة، لكن يمكن دمجه مع مكتبات مثل Shot أو Paparazzi. يحضر Espresso واجهة المستخدم في الحالة المطلوبة، وتأخذ مكتبة المقارنة لقطة شاشة وتقارنها بالمرجع. يُسمى هذا النهج اختبار الانحدار البصري ويساعد في العثور على تغييرات غير متوقعة في الواجهة.

الملخص

  • Espresso — إطار اختبار واجهة مستخدم Android من Google مع مزامنة تلقائية.
  • ViewMatchers — واجهة برمجة تطبيقات للبحث عن العناصر بواسطة ID والنص والتسلسل الهرمي والمجموعات.
  • ViewActions — click، typeText، scrollTo، swipe للتفاعل مع واجهة المستخدم.
  • ViewAssertions — matches، doesNotExist للتحقق من حالة العناصر.
  • Idling Resource — مزامنة الاختبار مع العمليات غير المتزامنة و coroutines.
  • ثلاث خطوات — onView().perform().check() = ابحث، نفذ، تحقق.
  • AndroidX Test — مكتبات لتشغيل الاختبارات الآلية على المحاكي أو الجهاز.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا