เว็บเอสเปรสโซ

Espresso-Web เป็นจุดแรกเข้าในการทำงานกับคอมโพเนนต์ UI ของ Android WebView Espresso-Web จะใช้ Atom ซ้ำจาก WebDriver API ยอดนิยมเพื่อตรวจสอบและควบคุมลักษณะการทำงานของ WebView

เมื่อใดที่ควรใช้ Espresso-Web

ใช้ Espresso-Web เพื่อทดสอบแอปแบบไฮบริด โดยเฉพาะการผสานรวมคอมโพเนนต์ UI ดั้งเดิมของแอปกับคอมโพเนนต์ UI ของ WebView คุณใช้ Espresso-Web API ร่วมกับ Espresso API อื่นๆ เพื่อโต้ตอบกับองค์ประกอบเว็บภายในออบเจ็กต์ WebView ได้อย่างเต็มที่

หากต้องการทดสอบเฉพาะ WebView เอง ไม่ใช่การโต้ตอบระหว่าง WebView กับคอมโพเนนต์ดั้งเดิมในแอป ให้ลองเขียนการทดสอบเว็บทั่วไปโดยใช้เฟรมเวิร์ก เช่น WebDriver หากใช้เฟรมเวิร์กการทดสอบเว็บ คุณไม่จำเป็นต้องใช้อุปกรณ์ Android หรือ Java Virtual Machine ซึ่งจะช่วยให้การทดสอบทำงานได้รวดเร็วและเชื่อถือได้มากขึ้น อย่างไรก็ตาม Espresso-Web ช่วยให้คุณนำ WebDriver Atom ที่กำหนดเองกลับมาใช้ซ้ำได้ ซึ่งจะช่วยให้มีความยืดหยุ่นเป็นอย่างมาก โดยเฉพาะเมื่อเขียนการทดสอบที่คุณวางแผนที่จะเรียกใช้กับทั้งเว็บแอปแบบสแตนด์อโลนและแอปที่มี UI ของ Android

วิธีการทำงาน

การโต้ตอบ WebView ประกอบด้วย Atom หลายรายการ ซึ่งคล้ายคลึงกับเมธอด onData() ของ Espresso การโต้ตอบ WebView ใช้ภาษาโปรแกรม Java ร่วมกับบริดจ์ JavaScript ในการทำงาน เนื่องจากไม่มีโอกาสที่จะเกิดภาวะแข่งขันโดยการเปิดเผยข้อมูลจากสภาพแวดล้อม JavaScript (ทุกสิ่งที่ Espresso เห็นในฝั่งที่ใช้ Java นั้นเป็นสำเนาที่แยกต่างหาก) ระบบจึงรองรับการส่งคืนข้อมูลจากออบเจ็กต์ Web.WebInteraction อย่างเต็มที่ ซึ่งช่วยให้คุณยืนยันข้อมูลทั้งหมดที่ส่งคืนจากคำขอได้

WebDriver Atom คืออะไร

เฟรมเวิร์ก WebDriver ใช้ Atom เพื่อค้นหาและจัดการองค์ประกอบของเว็บโดยใช้โปรแกรม WebDriver ใช้ Atom เพื่ออนุญาตการจัดการเบราว์เซอร์ ในเชิงแนวคิดแล้ว Atom จะคล้ายกับ ViewAction ซึ่งเป็นหน่วยแบบสแตนด์อโลนที่ดำเนินการใน UI คุณจะแสดง Atom โดยใช้รายการของเมธอดที่กำหนด เช่น findElement() และ getElement() เพื่อขับเคลื่อนเบราว์เซอร์จากมุมมองของผู้ใช้ อย่างไรก็ตาม หากคุณใช้เฟรมเวิร์ก WebDriver โดยตรง คุณจะต้องจัดการ Atom เป็นกลุ่มอย่างเหมาะสม ซึ่งต้องใช้ตรรกะที่ค่อนข้างซับซ้อน

ใน Espresso คลาส Web และ Web.WebInteraction จะทำหน้าที่ห่อหุ้ม Boilerplate นี้และมอบประสบการณ์การใช้งานที่เหมือนกับ Espresso ในการโต้ตอบกับออบเจ็กต์ WebView ดังนั้นในบริบทของ WebView ระบบจะใช้ Atom เป็นการแทนที่ Espresso ViewMatchers และ ViewActions แบบเดิม

จากนั้น API ก็จะดูเรียบง่ายขึ้น

Kotlin

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

Java

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

ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบของ Selenium เกี่ยวกับ Atom

ติดตั้งใช้งาน WebView

ทำตามคำแนะนำที่แสดงในส่วนต่อไปนี้เพื่อทำงานกับ WebView ในการทดสอบของแอป

แพ็กเกจ

หากต้องการรวม Espresso-Web ไว้ในโปรเจ็กต์ ให้ทำตามขั้นตอนต่อไปนี้

  1. เปิดไฟล์ build.gradle ของแอป โดยปกติแล้วไฟล์นี้จะไม่ใช่ไฟล์ build.gradle ระดับบนสุด แต่จะเป็น app/build.gradle
  2. เพิ่มบรรทัดต่อไปนี้ภายในทรัพยากร Dependency

    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() เป็นจุดแรกเข้าหลักเมื่อทำงานกับ 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 ดังนั้น WebView ที่อยู่ภายใต้การทดสอบต้องเปิดใช้ JavaScript เพื่อรองรับการประเมิน 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