Espresso Web

Espresso-Web 是一个与 Android WebView 界面组件配合使用的入口点。 Espresso-Web 重复使用常用 WebDriver API 中的 Atom 来检查和控制 WebView 的行为。

何时使用 Espresso-Web

使用 Espresso-Web 测试混合应用,尤其是 应用的原生界面组件及其 WebView 界面组件。您可以将 Espresso-Web API 与其他 API 结合使用。 Espresso API,用于与 WebView 对象内的 Web 元素进行全面交互。

如果您只需要测试 WebView 本身,而不测试 WebView 与应用中的原生组件之间的交互时,请考虑 使用 WebDriver 等框架编写常规 Web 测试。如果您使用网络测试框架 需要使用 Android 设备或 Java 虚拟机 更快、更可靠地运行。尽管如此,借助 Espresso-Web, 这可为您提供很大的灵活性,尤其是 以及计划针对独立 Web 应用和 包含 Android 界面的应用。

工作原理

类似于 Espresso 的 onData() 方法,WebView 交互包含多个 Atom。 WebView 交互结合使用 Java 编程语言和 来完成工作所需的 JavaScript 桥接因为没有机会引入 从 JavaScript 环境中公开 JavaScript 环境中的所有数据, Espresso 在基于 Java 的端认为是一个隔离的副本,即从 Web.WebInteraction 对象,从而让您能够验证从 请求。

什么是 WebDriver Atom?

WebDriver 框架使用 Atom 查找和操纵网络元素 以编程方式Atom 由 WebDriver 用来进行浏览器操纵。一个 Atom 在概念上类似于 ViewAction,一个独立的 执行操作的单元您可以使用 定义的方法(如 findElement()getElement())来驱动 从用户的角度对浏览器进行定制不过,如果您使用 WebDriver 框架,因此 Atom 需要经过适当编排,这需要 非常冗长

在 Espresso 中,Web 类 和Web.WebInteraction 封装此样板,并在与 WebView 交互时给人一种 Espresso 般的感觉 对象的操作。因此,在 WebView 的上下文中,Atom 用作 取代了传统的 Espresso ViewMatchersViewActions

于是,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. 在依赖项内添加以下代码行:

    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 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 找到了 ID 为 "link_2" 的 DOM 元素, 点击它。然后,该工具验证 WebView 是否发送 GET 请求 包含 "navigation_2.html" 字符串。

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() 引用 WebView 中的 DOM 元素。

    示例:

    Kotlin

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

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
    
  • <ph type="x-smartling-placeholder"></ph> 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"));
    
  • <ph type="x-smartling-placeholder"></ph> 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")));
    
  • <ph type="x-smartling-placeholder"></ph> 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)));
}

其他资源

如需详细了解如何在 Android 测试中使用 Espresso-Web,请查阅 以下资源。

示例