Espresso-Web هي نقطة دخول للعمل مع مكوّنات واجهة مستخدم Android WebView. تعيد Espresso-Web استخدام عناصر Atoms من WebDriver API الشائعة لفحص سلوك WebView والتحكّم فيه.
حالات استخدام Espresso-Web
استخدِم Espresso-Web لاختبار تطبيقاتك المختلطة، خاصةً تكامل مكوّنات واجهة المستخدم الأصلية لتطبيقك مع مكوّنات واجهة المستخدم WebView. يمكنك استخدام Espresso-Web API مع واجهات Espresso API الأخرى للتفاعل بشكل كامل مع عناصر الويب داخل كائنات 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 وحدات Atom للسماح بالتحكّم في المتصفّح. يشبه
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 في مشروعك، أكمل الخطوات التالية:
- افتح ملف
build.gradleفي تطبيقك. ولا يكون هذا الملف عادةً هو ملفbuild.gradleذو المستوى الأعلى، بل يكونapp/build.gradle. أضِف السطر التالي داخل التبعيات:
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-web:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
لا يتوافق 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.