Espresso-Intents هي إضافة إلى Espresso تتيح التحقّق من الأهداف التي يرسلها التطبيق قيد الاختبار وإنشاء نماذج لها. وهي تشبه Mockito، ولكنها مخصّصة لأهداف Android.
إذا كان تطبيقك يفوّض وظائف إلى تطبيقات أخرى أو إلى النظام الأساسي، يمكنك استخدام Espresso-Intents للتركيز على منطق تطبيقك مع افتراض أنّ التطبيقات الأخرى أو النظام الأساسي ستعمل بشكل صحيح. باستخدام Espresso-Intents، يمكنك مطابقة والتحقّق من صحة النوايا الصادرة أو حتى تقديم ردود تجريبية بدلاً من الردود الفعلية على النوايا.
تضمين Espresso-Intents في مشروعك
في ملف app/build.gradle
الخاص بتطبيقك، أضِف السطر التالي داخل dependencies
:
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-intents:3.6.1')
لا تتوافق Espresso-Intents إلا مع الإصدار 2.1 والإصدارات الأحدث من Espresso والإصدار 0.3 والإصدارات الأحدث من مكتبات اختبار Android، لذا احرص على تعديل هذه الأسطر أيضًا:
Groovy
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Kotlin
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
كتابة قواعد الاختبار
قبل كتابة اختبار Espresso-Intents، عليك إعداد IntentsTestRule
. هذا هو امتداد للفئة ActivityTestRule
ويسهّل استخدام واجهات برمجة التطبيقات Espresso-Intents في اختبارات واجهة المستخدم الوظيفية. يُهيئ IntentsTestRule
Espresso-Intents قبل كل اختبار تمّت إضافة التعليق التوضيحي @Test
إليه، ويحرّر IntentsTestRule
Espresso-Intents بعد كل عملية تشغيل اختبار.
مقتطف الرمز التالي هو مثال على IntentsTestRule
:
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
المطابقة
توفّر Espresso-Intents إمكانية اعتراض النوايا الصادرة استنادًا إلى معايير مطابقة معيّنة، يتم تحديدها باستخدام Hamcrest Matchers. تتيح لك مكتبة Hamcrest إجراء ما يلي:
- استخدام أداة مطابقة أهداف حالية: هذا هو الخيار الأسهل، ويجب تفضيله دائمًا تقريبًا.
- تنفيذ أداة مطابقة النية الخاصة بك: هذا هو الخيار الأكثر مرونة. تتوفّر تفاصيل إضافية في القسم بعنوان "كتابة أدوات مطابقة مخصّصة" ضمن برنامج Hamcrest التعليمي.
توفّر Espresso-Intents الطريقتَين intended()
وintending()
للتحقّق من صحة الأهداف وإنشاء نماذج لها على التوالي. تتلقّى كلتا الدالتَين عنصر Matcher<Intent>
من Hamcrest كمعلَمة.
يعرض مقتطف الرمز البرمجي التالي عملية التحقّق من صحة الهدف التي تستخدم أدوات مطابقة الأهداف الحالية التي تطابق هدفًا صادرًا يبدأ متصفحًا:
Kotlin
assertThat(intent).hasAction(Intent.ACTION_VIEW) assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE) assertThat(intent).hasData(Uri.parse("www.google.com")) assertThat(intent).extras().containsKey("key1") assertThat(intent).extras().string("key1").isEqualTo("value1") assertThat(intent).extras().containsKey("key2") assertThat(intent).extras().string("key2").isEqualTo("value2")
Java
assertThat(intent).hasAction(Intent.ACTION_VIEW); assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE); assertThat(intent).hasData(Uri.parse("www.google.com")); assertThat(intent).extras().containsKey("key1"); assertThat(intent).extras().string("key1").isEqualTo("value1"); assertThat(intent).extras().containsKey("key2"); assertThat(intent).extras().string("key2").isEqualTo("value2");
التحقّق من صحة المقاصد
تسجّل Espresso-Intents جميع الأهداف التي تحاول تشغيل الأنشطة من التطبيق قيد الاختبار. باستخدام طريقة intended()
، المشابهة لطريقة Mockito.verify()
، يمكنك التأكّد من أنّه تم رصد هدف معيّن. ومع ذلك، لا تحذف Espresso-Intents الردود على الأهداف إلا إذا ضبطتها بشكل صريح على ذلك.
مقتطف الرمز البرمجي التالي هو مثال على اختبار يتحقّق من صحة غرض صادر يطلق نشاطًا خارجيًا "للهاتف"، ولكنّه لا ينشئ رمزًا بديلًا للردود على هذا الغرض:
Kotlin
@Test fun validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)) // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")) }
Java
@Test public void validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)); // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")); }
إنشاء نماذج أولية
باستخدام طريقة intending()
، المشابهة لطريقة Mockito.when()
، يمكنك تقديم ردّ وهمي للأنشطة التي يتم تشغيلها باستخدام startActivityForResult()
. ويكون ذلك مفيدًا بشكل خاص للأنشطة الخارجية، لأنّه لا يمكنك معالجة واجهة المستخدم الخاصة بنشاط خارجي أو التحكّم في ActivityResult
الذي يتم عرضه للنشاط قيد الاختبار.
تنفِّذ مقتطفات الرموز البرمجية التالية مثالاً
activityResult_DisplaysContactsPhoneNumber()
لاختبار، يتحقّق من أنّه عندما يشغّل
المستخدم نشاط "جهة اتصال" في التطبيق قيد الاختبار، يتم عرض رقم هاتف جهة الاتصال:
إنشاء النتيجة التي سيتم عرضها عند تشغيل نشاط معيّن يعترض اختبار المثال جميع Intent التي يتم إرسالها إلى "جهات الاتصال" ويستبدل ردودها بـ
ActivityResult
صالح، باستخدام رمز النتيجةRESULT_OK
.Kotlin
val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
Java
Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
اطلب من Espresso تقديم عنصر نتيجة فارغ استجابةً لجميع عمليات استدعاء الغرض "جهات الاتصال":
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
تأكَّد من أنّ الإجراء المستخدَم لتشغيل النشاط ينتج عنه نتيجة رمزية متوقّعة. في هذه الحالة، يتحقّق الاختبار النموذجي من أنّه يتم عرض رقم الهاتف 123-345-6789 عند تشغيل "نشاط جهات الاتصال":
Kotlin
onView(withId(R.id.pickButton)).perform(click()) onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
Java
onView(withId(R.id.pickButton)).perform(click()); onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
في ما يلي اختبار activityResult_DisplaysContactsPhoneNumber()
الكامل:
Kotlin
@Test fun activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result) // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()) // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))) }
Java
@Test public void activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData); // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result); // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()); // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))); }
مراجع إضافية
لمزيد من المعلومات حول استخدام Espresso-Intents في اختبارات Android، يُرجى الرجوع إلى المراجع التالية.
نماذج
- IntentsBasicSample:
الاستخدام الأساسي لـ
intended()
وintending()
- IntentsAdvancedSample: يحاكي هذا التطبيق مستخدمًا يسترد صورة نقطية باستخدام الكاميرا.