أغراض إسبريسو

Espresso-Intents هي إضافة لخيار Espresso، ما يتيح إمكانية التحقّق من النية التي يرسلها التطبيق الذي يخضع للاختبار واستبعاده. إنها مثل Mockito، لكنها مخصصة لأهداف Android Intent.

إذا فوّض تطبيقك وظائف تطبيقات أخرى أو نظام أساسي آخر، يمكنك استخدام Espresso-Intents للتركيز على منطق تطبيقك مع افتراض أنّ التطبيقات الأخرى أو النظام الأساسي ستعمل على نحو سليم. وباستخدام Espresso-Intents، يمكنك مطابقة نواياك الصادرة والتحقق منها أو حتى تقديم ردود كعبة بدلاً من الردود الفعلية على النية.

تضمين Espresso-Intents في مشروعك

في ملف app/build.gradle لتطبيقك، أضِف السطر التالي داخل dependencies:

رائع

androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0'

Kotlin

androidTestImplementation('androidx.test.espresso:espresso-intents:3.4.0')

لا يتوافق Espresso-Intents إلا مع إصدار Espresso 2.1 والإصدارات الأحدث منه، ومع الإصدارات 0.3 والإصدارات الأحدث من مكتبات الاختبار على Android، لذا احرص على تعديل هذه الأسطر أيضًا:

رائع

androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

Kotlin

androidTestImplementation('androidx.test:runner:1.4.0')
androidTestImplementation('androidx.test:rules:1.4.0')
androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')

كتابة قواعد الاختبار

قبل كتابة اختبار Espresso-Intents، يجب إعداد IntentsTestRule. هذه إضافة للفئة ActivityTestRule وتسهّل استخدام واجهات برمجة تطبيقات Espresso-Intents في الاختبارات الوظيفية لواجهة المستخدم. يعمل IntentsTestRule على إعداد Espresso-Intents قبل كل اختبار تتم إضافة تعليقات توضيحية إليه باستخدام @Test وإصدار 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() للتحقّق من النية واستبدالها على التوالي. كلتاهما تستخدمان كائن Hamcrest Matcher<Intent> كوسيطة.

يعرض مقتطف الرمز التالي عملية التحقّق من النية التي تستخدم أدوات مطابقة الأهداف الحالية التي تتطابق مع غرض صادر يبدأ تشغيل متصفّح:

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() الذي يتحقّق من عرض رقم هاتف جهة الاتصال عندما يبدأ المستخدم نشاط "جهة اتصال" في التطبيق قيد الاختبار:

  1. أنشئ النتيجة لإرجاعها عند إطلاق نشاط معين. ويعترض اختبار هذا المثال جميع الأهداف المرسَلة إلى "جهات الاتصال"، ويتجاهل ردودها باستخدام رمز 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);
    
  2. اطلب من Espresso تقديم كائن نتيجة التلميح ردًا على جميع الاستدعاءات لغرض "جهات الاتصال":

    Kotlin

    intending(toPackage("com.android.contacts")).respondWith(result)
    

    Java

    intending(toPackage("com.android.contacts")).respondWith(result);
    
  3. تحقق من أن الإجراء المستخدم لبدء النشاط ينتج عنه نتيجة الكعب المتوقعة. في هذه الحالة، يتحقّق نموذج الاختبار من عرض رقم الهاتف "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، يُرجى الرجوع إلى المراجع التالية.

عيّنات