إسبريسو ويب

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

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

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

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

طريقة العمل

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

ما هي WebDriver Atom؟

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

ضمن Espresso، Web وWeb.WebInteraction تلتفيان هذا النص النموذجي وتمنحهما طابعًا يشبه الإسبريسو عند التفاعل مع عناصر WebView. لذلك في سياق WebView، يتم استخدام Atom كبديل لقهوة الإسبريسو التقليدية ViewMatchers وViewActions.

عندئذٍ تبدو واجهة برمجة التطبيقات بسيطة للغاية:

Kotlin

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

Java

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

لمعرفة المزيد من المعلومات، يمكنك الاطّلاع على وثائق مكتبة سيلينيوم عن وحدات Atom.

تنفيذ WebView

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

الطرود

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

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

    رائع

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

    Kotlin

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

    رائع

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

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

إنّ الطريقة 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 وWindowsReference.

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

    مثال:

    Kotlin

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

    Java

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

مثال

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

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، يُرجى الرجوع إلى الموارد التالية.

عيّنات

  • WebBasicعيّن: يمكنك استخدام Espresso-Web للتفاعل مع كائنات WebView.