Espresso Web

Espresso-Web là một điểm truy cập để hoạt động với các thành phần giao diện người dùng WebView của Android. Espresso-Web sử dụng lại các Atom trong API WebDriver phổ biến để kiểm tra và kiểm soát hành vi của một WebView.

Thời điểm sử dụng Espresso-Web

Sử dụng Espresso-Web để kiểm thử các ứng dụng kết hợp, đặc biệt là việc tích hợp các thành phần giao diện người dùng gốc của ứng dụng với các thành phần giao diện người dùng WebView của ứng dụng đó. Bạn có thể sử dụng Espresso-Web API cùng với các API Espresso khác để tương tác đầy đủ với các phần tử web bên trong đối tượng WebView.

Nếu bạn chỉ cần kiểm thử chính WebView chứ không cần kiểm thử các lượt tương tác giữa WebView và các thành phần gốc trong ứng dụng, hãy cân nhắc viết một chương trình kiểm thử web chung bằng một khung như WebDriver. Nếu sử dụng khung kiểm thử web, bạn không cần phải sử dụng thiết bị Android hoặc Máy ảo Java. Nhờ đó, các hoạt động kiểm thử của bạn sẽ chạy nhanh và đáng tin cậy hơn. Dù vậy, Espresso-Web cho phép bạn sử dụng lại các nguyên tử WebDriver tuỳ chỉnh, giúp bạn rất linh hoạt, đặc biệt là khi viết chương trình kiểm thử mà bạn định chạy trên cả ứng dụng web độc lập và ứng dụng có giao diện người dùng Android.

Cách hoạt động

Tương tự như phương thức onData() của Espresso, hoạt động tương tác với WebView bao gồm một số Atom. Các hoạt động tương tác WebView sử dụng kết hợp ngôn ngữ lập trình Java và cầu JavaScript để thực hiện công việc. Vì không thể giới thiệu điều kiện tương tranh bằng cách hiển thị dữ liệu từ môi trường JavaScript – mọi thứ mà Espresso nhìn thấy ở phía dựa trên Java đều là một bản sao riêng biệt. Việc trả về dữ liệu từ các đối tượng Web.WebInteraction đều được hỗ trợ đầy đủ, cho phép bạn xác minh mọi dữ liệu được trả về từ một yêu cầu.

WebDriver Atom là gì?

Khung WebDriver sử dụng Atoms để tìm và thao tác với các phần tử web theo phương thức lập trình. WebDriver sử dụng Atom để cho phép thao tác trên trình duyệt. Về mặt lý thuyết, Atom tương tự như một ViewAction, một đơn vị độc lập thực hiện một hành động trong giao diện người dùng của bạn. Bạn hiển thị Atom bằng một danh sách các phương thức đã xác định, chẳng hạn như findElement()getElement(), để điều khiển trình duyệt theo quan điểm của người dùng. Tuy nhiên, nếu bạn sử dụng trực tiếp khung WebDriver, thì Atoms cần được sắp xếp đúng cách, đòi hỏi logic khá chi tiết.

Trong Espresso, các lớp WebWeb.WebInteraction sẽ bao bọc mẫu mã nguyên mẫu này và mang lại cảm giác giống như Espresso khi tương tác với các đối tượng WebView. Vì vậy, trong bối cảnh của WebView, Atom được dùng để thay thế cho Espresso ViewMatchersViewActions truyền thống.

Khi đó, API sẽ trông khá đơn giản:

Kotlin

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

Java

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

Để tìm hiểu thêm, hãy đọc tài liệu của Selenium về Atoms.

Triển khai WebView

Làm theo hướng dẫn trong các phần sau để làm việc với WebView trong các kiểm thử của ứng dụng.

Gói

Để đưa Espresso-Web vào dự án của bạn, hãy hoàn tất các bước sau:

  1. Mở tệp build.gradle của ứng dụng. Tệp này thường không phải là tệp build.gradle cấp cao nhất mà là app/build.gradle.
  2. Hãy thêm dòng sau bên trong phần phụ thuộc:

    Groovy

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

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.4.0')
        
  3. Espresso-Web chỉ tương thích với Espresso 2.2 trở lên và phiên bản 0.3 trở lên của thư viện kiểm thử. Vì vậy, hãy nhớ cập nhật các dòng đó:

    Groovy

        androidTestImplementation 'androidx.test:runner:1.4.0'
        androidTestImplementation 'androidx.test:rules:1.4.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
        

    Kotlin

        androidTestImplementation('androidx.test:runner:1.4.0')
        androidTestImplementation('androidx.test:rules:1.4.0')
        androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')
        

Cách sử dụng API phổ biến

Phương thức onWebView() là điểm truy cập chính khi làm việc với WebView trên Android bằng Espresso. Bạn sẽ sử dụng phương thức này để kiểm thử Espresso-Web, chẳng hạn như sau:

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")));

Trong ví dụ này, Espresso-Web xác định vị trí một phần tử DOM có mã nhận dạng là "link_2" và nhấp vào phần tử đó. Sau đó, công cụ này sẽ xác minh rằng WebView sẽ gửi yêu cầu GET chứa chuỗi "navigation_2.html".

Hỗ trợ JavaScript

Khi thực thi kiểm thử của bạn, hệ thống sẽ thực hiện tất cả các lượt tương tác với WebView bằng JavaScript. Do đó, để hỗ trợ đánh giá JavaScript, WebView đang được kiểm thử phải bật JavaScript.

Bạn có thể buộc bật JavaScript bằng cách gọi forceJavascriptEnabled() dưới dạng một hành động trong hoạt động đang được kiểm thử, như minh hoạ trong đoạn mã sau đây.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

Các hoạt động tương tác phổ biến trên web

Sau đây là các hoạt động tương tác phổ biến với các đối tượng Web.WebInteraction:

  • withElement() tham chiếu đến một phần tử DOM trong WebView.

    Ví dụ:

    Kotlin

    onWebView().withElement(findElement(Locator.ID, "teacher"))
    

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
    
  • withContextualElement() tham chiếu đến một phần tử DOM trong phạm vi trong WebView, so với một phần tử DOM khác. Trước tiên, bạn nên gọi withElement() để thiết lập đối tượng tham chiếu Web.WebInteraction (phần tử DOM).

    Ví dụ:

    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() đánh giá một điều kiện, đảm bảo điều kiện đó được phân giải thành true.

    Ví dụ:

    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() thực thi một thao tác trong WebView, chẳng hạn như nhấp vào một phần tử.

    Ví dụ:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())
    

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
    
  • reset() chuyển WebView về trạng thái ban đầu. Điều này cần thiết khi một thao tác trước đó (chẳng hạn như một lượt nhấp) tạo ra thay đổi điều hướng khiến các đối tượng ElementReference và WindowReference không thể truy cập được.

    Lưu ý: Mặc dù việc sử dụng reset() sẽ hữu ích khi đưa ra câu nhận định trong quy trình làm việc nhiều trang (chẳng hạn như gửi biểu mẫu), nhưng các bài kiểm thử của bạn thường chỉ nên giới hạn trong phạm vi và tập trung vào một trang duy nhất.

    Ví dụ:

    Kotlin

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()
    

    Java

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();
    

Ví dụ

Ví dụ sau đây kiểm tra xem liệu sau khi nhập văn bản vào WebView và chọn nút Submit (Gửi), văn bản đó có xuất hiện trong một phần tử khác trong cùng một WebView hay không:

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)));
}

Tài nguyên khác

Để biết thêm thông tin về cách sử dụng Espresso-Web trong kiểm thử Android, hãy tham khảo các tài nguyên sau.

Mẫu

  • WebBasicSample: Sử dụng Espresso-Web để tương tác với các đối tượng WebView.