אספרסו אינטרנט

‫Espresso-Web היא נקודת כניסה לעבודה עם רכיבי ממשק משתמש של Android WebView. ‫Espresso-Web משתמש מחדש ב-Atoms מ-WebDriver API הפופולרי כדי לבדוק את ההתנהגות של WebView ולשלוט בה.

מתי כדאי להשתמש ב-Espresso-Web

כדאי להשתמש ב-Espresso-Web כדי לבדוק את האפליקציות ההיברידיות, במיוחד את השילוב של רכיבי ממשק המשתמש המקוריים של האפליקציה עם רכיבי ממשק המשתמש שלה.WebView אפשר להשתמש ב-Espresso-Web API בשילוב עם ממשקי API אחרים של Espresso כדי ליצור אינטראקציה מלאה עם רכיבי אינטרנט בתוך אובייקטים של WebView.

אם אתם צריכים לבדוק רק את WebView עצמו, ולא את האינטראקציות בין WebView לבין רכיבים מקוריים באפליקציה, כדאי לכתוב בדיקת אינטרנט כללית באמצעות מסגרת כמו WebDriver. אם משתמשים במסגרת לבדיקת אתרים, לא צריך להשתמש במכשיר Android או במכונה וירטואלית של Java, ולכן הבדיקות יפעלו מהר יותר ובאופן מהימן יותר. עם זאת, Espresso-Web מאפשר לכם לעשות שימוש חוזר באטומי WebDriver מותאמים אישית, מה שמעניק לכם גמישות רבה, במיוחד כשכותבים בדיקות שמתכננים להריץ גם באפליקציות אינטרנט עצמאיות וגם באפליקציות שכוללות ממשק משתמש של Android.

איך זה עובד

בדומה לשיטה onData() של Espresso, אינטראקציה מסוג WebView מורכבת מכמה אטומים. אינטראקציות WebView משתמשות בשילוב של שפת התכנות Java וגשר JavaScript כדי לבצע את העבודה. מכיוון שאין סיכוי להיווצרות מצבי מירוץ בחשיפת נתונים מסביבת JavaScript – כל מה ש-Espresso רואה בצד שמבוסס על Java הוא עותק מבודד – יש תמיכה מלאה בהחזרת נתונים מאובייקטים של Web.WebInteraction, כך שאפשר לאמת את כל הנתונים שמוחזרים מבקשה.

מה זה WebDriver Atom?

מסגרת WebDriver משתמשת ב-Atoms כדי למצוא ולשנות רכיבי אינטרנט באופן פרוגרמטי. ‫WebDriver משתמש ב-Atoms כדי לאפשר שינוי בדפדפן. מבחינה רעיונית, Atom דומה ל-ViewAction, יחידה עצמאית שמבצעת פעולה בממשק המשתמש. אתם חושפים את ה-Atoms באמצעות רשימה של שיטות מוגדרות, כמו findElement() ו-getElement(), כדי להפעיל את הדפדפן מנקודת המבט של המשתמש. עם זאת, אם משתמשים ישירות ב-framework של WebDriver, צריך לתזמן את ה-Atoms בצורה נכונה, וזה דורש לוגיקה מפורטת למדי.

ב-Espresso, המחלקות Web ו-Web.WebInteraction עוטפות את הקוד הסטנדרטי הזה ויוצרות אינטראקציה עם אובייקטים של WebView שדומה ל-Espresso. לכן, בהקשר של WebView, נעשה שימוש ב-Atoms כתחליף ל-Espresso ViewMatchers וViewActions.

ה-API נראה פשוט למדי:

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. מוסיפים את השורה הבאה בתוך dependencies:

    גרוב

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

שימוש נפוץ ב-API

השיטה 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 ולוחצים על הלחצן Submit (שליחה), אותו טקסט מופיע ברכיב אחר באותו 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: Use Espresso-Web to interact with WebView objects.