اختبار الواجهة باستخدام Espresso
اكتبوا اختبارات آلية للواجهة باستخدام Espresso. اعثروا على الواجهات باستخدام onView()، وتفاعلوا معها باستخدام perform()، وتحقّقوا من حالتها باستخدام check()، واختبروا تفاعلات RecyclerView.
اختبار الواجهة باستخدام Espresso درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Android Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Android Academy 4 دروس في المجموع.
ما المقصود بـ Espresso؟
Espresso هو إطار Android الرسمي لاختبار واجهة المستخدم. يتيح لك كتابة اختبارات تتفاعل مع واجهة تطبيقك، مثل النقر على الأزرار وكتابة النصوص والتمرير في القوائم، ثم التحقق مما يظهر على الشاشة.
يعمل Espresso على جهاز أو محاكي (اختبار مزوّد بالأجهزة)، ويزامن نفسه تلقائيًا مع خيط واجهة المستخدم، لذلك لا حاجة إلى استدعاءات sleep() غير الموثوقة.
الإعداد
يُضمّن Espresso في حزمة أدوات اختبار Android. أضف الاعتماديات التالية إلى app/build.gradle:
// app/build.gradle:
android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' // RecyclerView
}ActivityScenarioRule
استخدم ActivityScenarioRule لتشغيل Activity قبل كل اختبار وإغلاقها بعده:
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(LoginActivity::class.java)
@Test
fun `login button is displayed`() {
onView(withId(R.id.btnLogin))
.check(matches(isDisplayed()))
}
}onView() وViewMatchers
تعثر onView(matcher) على طريقة عرض ضمن التسلسل الهرمي الحالي. ادمج أدوات المطابقة للحصول على دقة أكبر:
// Match by ID:
onView(withId(R.id.tvTitle))
// Match by text:
onView(withText("Submit"))
// Match by content description (for accessibility):
onView(withContentDescription("Close dialog"))
// Combine matchers:
onView(allOf(withId(R.id.btnSave), isEnabled()))
// Inside a specific parent:
onView(withId(R.id.btnSave)).inRoot(isDialog())ViewActions — التفاعل مع طرق العرض
بعد العثور على طريقة عرض، نفّذ إجراءً باستخدام .perform():
// Tap a button:
onView(withId(R.id.btnLogin)).perform(click())
// Type into an EditText:
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Clear text and retype:
onView(withId(R.id.etPassword))
.perform(clearText(), typeText("secret123"), closeSoftKeyboard())
// Scroll to a view:
onView(withId(R.id.btnSubmit)).perform(scrollTo(), click())
// Long press:
onView(withId(R.id.ivImage)).perform(longClick())ViewAssertions — التحقق من الحالة
تحقق مما يظهر على الشاشة باستخدام .check():
// View is displayed:
onView(withId(R.id.tvError)).check(matches(isDisplayed()))
// View has specific text:
onView(withId(R.id.tvTitle)).check(matches(withText("Welcome!")))
// View is not displayed (GONE or INVISIBLE):
onView(withId(R.id.progressBar)).check(matches(not(isDisplayed())))
// View is enabled:
onView(withId(R.id.btnSave)).check(matches(isEnabled()))
// View does not exist:
onView(withId(R.id.tvError)).check(doesNotExist())اختبار تسجيل دخول كامل
اختبار كامل يكتب بيانات الاعتماد وينقر على تسجيل الدخول:
@Test
fun `successful login shows home screen`() {
// Type email
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Type password
onView(withId(R.id.etPassword))
.perform(typeText("password123"), closeSoftKeyboard())
// Tap login button
onView(withId(R.id.btnLogin)).perform(click())
// Assert welcome message is shown
onView(withId(R.id.tvWelcome))
.check(matches(withText("Welcome, Alice!")))
}اختبار RecyclerView
استخدم RecyclerViewActions من espresso-contrib للتفاعل مع عناصر القائمة:
import androidx.test.espresso.contrib.RecyclerViewActions
@Test
fun `clicking item opens detail screen`() {
// Scroll to position 5 and click:
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
5, click()
))
// Assert detail screen is shown:
onView(withId(R.id.tvDetailTitle)).check(matches(isDisplayed()))
}اختبار التحقق من الإدخال
تحقق من ظهور رسائل الخطأ عند إدخال بيانات غير صالحة:
@Test
fun `empty email shows error message`() {
// Leave email blank, tap login
onView(withId(R.id.btnLogin)).perform(click())
// Assert error is shown
onView(withId(R.id.tilEmail))
.check(matches(hasDescendant(withText("Email is required"))))
}
@Test
fun `short password shows error`() {
onView(withId(R.id.etPassword))
.perform(typeText("123"), closeSoftKeyboard())
onView(withId(R.id.btnLogin)).perform(click())
onView(withId(R.id.tilPassword))
.check(matches(hasDescendant(withText("Minimum 6 characters"))))
}موارد الخمول
ينتظر Espresso تلقائيًا خمول خيط واجهة المستخدم، لكنه لا ينتظر استدعاءات الشبكة أو coroutines. استخدم IdlingResource لإخبار Espresso بالانتظار حتى يكتمل عملك غير المتزامن:
// CountingIdlingResource: increment before async work, decrement when done
val idlingResource = CountingIdlingResource("NetworkCall")
// In your ViewModel/Repository:
idlingResource.increment()
viewModelScope.launch {
loadData()
idlingResource.decrement()
}
// In test setUp:
@Before
fun setUp() {
IdlingRegistry.getInstance().register(idlingResource)
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(idlingResource)
}تشغيل اختبارات Espresso
شغّل الاختبارات المزوّدة بالأجهزة على جهاز متصل أو محاكي:
- في Android Studio: انقر بزر الفأرة الأيمن على فئة الاختبار ← Run
- عبر الطرفية:
./gradlew connectedAndroidTest - تظهر النتائج في
app/build/reports/androidTests/
استخدم Android Emulator API 28 أو إصدارًا أحدث للحصول على تشغيل مستقر وسريع للاختبارات. عطّل الرسوم المتحركة من إعدادات المطوّر لتجنب عدم استقرار الاختبارات.
تحقق سريع
ما النمط الصحيح في Espresso للعثور على طريقة عرض والتحقق من نصها؟
مراجعة: اختبار واجهة المستخدم باستخدام Espresso
يكشف اختبار واجهة المستخدم الآلي التراجعات قبل أن يكتشفها المستخدمون:
onView(matcher)— العثور على طريقة عرض.perform(action)— النقر والكتابة والتمرير.check(matches(...))— التأكد من الظهور والنص والحالةRecyclerViewActionsللتفاعل مع القوائمIdlingResourceللعمليات غير المتزامنة- عطّل رسوم النظام المتحركة لتجنب الاختبارات غير المستقرة
التالي: تصحيح أخطاء تطبيقك وتحليل أدائه باحتراف.
الأسئلة الشائعة
هل درس «اختبار الواجهة باستخدام Espresso» مجاني؟
نعم — نص درس «اختبار الواجهة باستخدام Espresso» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Android Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Android Academy 4 دروس في المجموع.
ماذا ستتعلم في «اختبار الواجهة باستخدام Espresso»؟
اكتبوا اختبارات آلية للواجهة باستخدام Espresso. اعثروا على الواجهات باستخدام onView()، وتفاعلوا معها باستخدام perform()، وتحقّقوا من حالتها باستخدام check()، واختبروا تفاعلات RecyclerView. تتمرن على Android Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Android Academy؟
لا تُشترط خبرة سابقة. Android Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «اختبار الواجهة باستخدام Espresso»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Android Academy هذا؟
نعم. كل درس في Android Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- اختبار الوحدات باستخدام JUnit
- المحاكاة باستخدام Mockito
- اختبار الواجهة باستخدام Espresso
- تصحيح الأخطاء وتحليل الأداء