إسبريسو ويب

‫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 عدة عناصر Atoms. تستخدم تفاعلات 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 كـ بديل لـ Espresso ViewMatchers و ViewActions التقليدية.

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

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 الخاص بتطبيقك. عادةً ما يكون هذا الملف هو app/build.gradle وليس ملف build.gradle على المستوى الأعلى.
  2. أضِف السطر التالي داخل التبعيات:

    أنيق

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

    Kotlin

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

    أنيق

        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، يجب تفعيل JavaScript في WebView قيد الاختبار.

يمكنك فرض تفعيل 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.