إسبريسو ويب

‫Espresso-Web هي نقطة دخول للعمل مع مكوّنات واجهة مستخدم Android WebView. تعيد Espresso-Web استخدام عناصر Atoms من WebDriver API الشائعة لفحص سلوك WebView والتحكّم فيه.

حالات استخدام Espresso-Web

استخدِم Espresso-Web لاختبار تطبيقاتك المختلطة، خاصةً تكامل مكوّنات واجهة المستخدم الأصلية لتطبيقك مع مكوّنات واجهة المستخدم WebView. يمكنك استخدام Espresso-Web API مع واجهات برمجة تطبيقات Espresso الأخرى للتفاعل بشكل كامل مع عناصر الويب داخل كائنات WebView.

إذا كنت بحاجة إلى اختبار WebView فقط، وليس التفاعلات بين WebView والمكوّنات الأصلية في تطبيقك، ننصحك بكتابة اختبار ويب عام باستخدام إطار عمل مثل WebDriver. إذا كنت تستخدم إطار عمل لاختبار الويب، لن تحتاج إلى استخدام جهاز Android أو جهاز Java الظاهري، ما يؤدي إلى تشغيل اختباراتك بشكل أسرع وأكثر موثوقية. مع ذلك، يتيح لك Espresso-Web إعادة استخدام وحدات WebDriver المخصّصة، ما يمنحك الكثير من المرونة، خاصةً عند كتابة اختبارات تخطّط لتنفيذها على كل من تطبيقات الويب المستقلة والتطبيقات التي تتضمّن واجهة مستخدم Android.

آلية العمل

على غرار طريقة onData() في Espresso، يتضمّن تفاعل WebView عدة وحدات Atom. تستخدم تفاعلات WebView مزيجًا من لغة البرمجة Java وجسر JavaScript لتنفيذ عملها. بما أنّه لا يمكن حدوث أي تداخل في البيانات من خلال عرض البيانات من بيئة JavaScript، لأنّ كل ما يراه Espresso على الجانب المستند إلى Java هو نسخة معزولة، فإنّ عرض البيانات من عناصر Web.WebInteraction متاح بالكامل، ما يتيح لك التحقّق من جميع البيانات التي يتم عرضها من طلب.

ما هو WebDriver Atom؟

يستخدم إطار عمل WebDriver عناصر Atoms للعثور على عناصر الويب ومعالجتها آليًا. تستخدم WebDriver عناصر Atoms للسماح بالتحكّم في المتصفّح. ‫Atom مشابهة من الناحية المفاهيمية ViewAction، وهي وحدة مستقلة ذاتيًا تنفّذ إجراءً في واجهة المستخدم. يمكنك عرض Atoms باستخدام قائمة بالطرق المحدّدة، مثل findElement() وgetElement()، لتوجيه المتصفّح من وجهة نظر المستخدم. ومع ذلك، إذا كنت تستخدم إطار عمل WebDriver مباشرةً، يجب تنظيم Atoms بشكل صحيح، ما يتطلب منطقًا مطوّلاً.

في Espresso، يغلّف الصنفان Web وWeb.WebInteraction هذا الرمز النموذجي ويمنحان شعورًا مشابهًا لـ Espresso عند التفاعل مع عناصر WebView. في سياق WebView، يتم استخدام Atoms كبديل لـ ViewMatchers وViewActions التقليديين في Espresso.

تبدو واجهة برمجة التطبيقات بسيطة جدًا:

Kotlin

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion)

Java

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion);

لمزيد من المعلومات، يُرجى الاطّلاع على مستندات Selenium حول Atoms.

تنفيذ WebView

اتّبِع الإرشادات الموضّحة في الأقسام التالية لاستخدام WebView في اختبارات تطبيقك.

إدارة الحِزم

لإدراج Espresso-Web في مشروعك، أكمل الخطوات التالية:

  1. افتح ملف build.gradle التطبيق. عادةً ما يكون هذا الملف ليس ملف build.gradle ذي المستوى الأعلى، بل app/build.gradle.
  2. أضِف السطر التالي داخل التبعيات:

    Groovy

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.6.1'
        

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
        
  3. لا يتوافق Espresso-Web إلا مع الإصدار 2.2 أو الإصدارات الأحدث من Espresso والإصدار 0.3 أو الإصدارات الأحدث من مكتبة الاختبار، لذا تأكَّد من تعديل هذه الأسطر أيضًا:

    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')
        

الاستخدام الشائع لواجهة برمجة التطبيقات

تُعدّ طريقة onWebView() نقطة الدخول الرئيسية عند استخدام WebView على Android باستخدام Espresso. يمكنك استخدام هذه الطريقة لإجراء اختبارات Espresso-Web، مثل ما يلي:

Kotlin

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))

Java

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));

في هذا المثال، يحدّد Espresso-Web عنصر DOM الذي يحمل المعرّف "link_2" وينقر عليه. بعد ذلك، تتحقّق الأداة من أنّ WebView يرسل طلب GET يحتوي على السلسلة "navigation_2.html".

التوافق مع JavaScript

عند تنفيذ الاختبارات، ينفّذ النظام جميع تفاعلات WebView باستخدام JavaScript. لذلك، يجب تفعيل JavaScript في WebView قيد الاختبار من أجل إتاحة تقييم JavaScript.

يمكنك فرض تفعيل JavaScript من خلال استدعاء forceJavascriptEnabled() كـ إجراء في نشاطك ضمن الاختبار، كما هو موضّح في مقتطف الرمز التالي.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

التفاعلات الشائعة على الويب

تشمل التفاعلات الشائعة مع عناصر Web.WebInteraction ما يلي:

  • يشير withElement() إلى عنصر DOM ضِمن WebView.

    مثال:

    Kotlin

    onWebView().withElement(findElement(Locator.ID, "teacher"))

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
  • يشير withContextualElement() إلى عنصر DOM ذي نطاق محدد ضمن WebView، وذلك بالنسبة إلى عنصر DOM آخر. يجب استدعاء withElement() أولاً لإنشاء مرجع Web.WebInteraction (عنصر DOM).

    مثال:

    Kotlin

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))

    Java

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"));
  • تقيّم الدالة check() شرطًا، مع التأكّد من أنّه يؤدي إلى القيمة true.

    مثال:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")))

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")));
  • ينفّذ perform() إجراءً داخل WebView، مثل النقر على عنصر.

    مثال:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
  • reset() تعيد WebView إلى حالتها الأولية. ويكون ذلك ضروريًا عندما يؤدي إجراء سابق، مثل النقر، إلى تغيير في عملية التنقّل يجعل عناصر ElementReference وWindowReference غير قابلة للوصول.

    ملاحظة: على الرغم من أنّ استخدام reset() مفيد عند تقديم تأكيدات بشأن سير العمل المتعدّد الصفحات، مثل عمليات إرسال النماذج، يجب عادةً أن تكون اختباراتك محدودة النطاق وتركز على صفحة واحدة.

    مثال:

    Kotlin

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()

    Java

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();

مثال

يختبر المثال التالي ما إذا كان النص نفسه يظهر ضمن عنصر مختلف في WebView نفسه بعد إدخال نص في WebView والنقر على زر إرسال:

Kotlin

const val MACCHIATO = "Macchiato"

@RunWith(AndroidJUnit4::class)
class MyEspressoWebTestSuite {

    @Test fun typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        val webFormIntent = Intent()
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent)

        // Selects the WebView in your layout. If you have multiple WebView
        // objects, you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)))
    }
}

Java

public static final String MACCHIATO = "Macchiato";

@Test
public void typeTextInInput_clickButton_SubmitsForm() {
    // Create an intent that displays a web form.
    Intent webFormIntent = new Intent();
    // ...

    // Lazily launch the Activity with a custom start Intent per test.
    ActivityScenario.launchActivity(webFormIntent);

    // Selects the WebView in your layout. If you have multiple WebView objects,
    // you can also use a matcher to select a given WebView,
    // onWebView(withId(R.id.web_view)).
    onWebView()
        // Find the input element by ID.
        .withElement(findElement(Locator.ID, "text_input"))

        // Clear previous input and enter new text into the input element.
        .perform(clearElement())
        .perform(DriverAtoms.webKeys(MACCHIATO))

        // Find the "Submit" button and simulate a click using JavaScript.
        .withElement(findElement(Locator.ID, "submitBtn"))
        .perform(webClick())

        // Find the response element by ID, and verify that it contains the
        // entered text.
        .withElement(findElement(Locator.ID, "response"))
        .check(webMatches(getText(), containsString(MACCHIATO)));
}

مراجع إضافية

لمزيد من المعلومات حول استخدام Espresso-Web في اختبارات Android، يُرجى الرجوع إلى المراجع التالية.

نماذج

  • WebBasicSample: استخدِم Espresso-Web للتفاعل مع عناصر WebView.