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

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

מתי להשתמש ב-Espresso-Web

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

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

איך זה עובד

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

מהו WebDriver Atom?

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

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

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

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

    Groovy

        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 ואילך של ספריית הבדיקות, לכן חשוב לעדכן אותן גם שורות:

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

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

onWebView() method היא נקודת הכניסה העיקרית כשעובדים עם WebView ב-Android באמצעות אספרסו. משתמשים בשיטה זו כדי לבצע בדיקות של 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 ו-WinReference לא נגישים.

    הערה: השימוש ב-reset() שימושי כאשר טענות נכוֹנוּת (assertions) לגבי תהליכי עבודה שכוללים דפים מרובים, כמו שליחות טפסים, הבדיקות בדרך כלל צריכות להיות מוגבלות ולהתמקד בדף יחיד.

    דוגמה:

    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 אובייקטים.