Espresso 测试框架 - WebView

WebView 是 Android 提供的一种特殊视图,用于在应用程序内显示网页。WebView 不提供像 chrome 和 firefox 这样的成熟浏览器应用程序的所有功能。但是,它提供了对要显示的内容的完全控制,并公开了要在网页内调用的所有 Android 功能。它启用了 WebView 并提供了一个特殊的环境,在该环境中,可以使用 HTML 技术和相机和拨打联系人等本机功能轻松设计 UI。此功能集使 WebView 能够提供一种称为 混合应用程序 的新型应用程序,其中 UI 以 HTML 完成,业务逻辑以 JavaScript 或通过外部 API 端点完成。

通常,测试 WebView 需要是一项挑战,因为它使用 HTML 技术作为其用户界面元素,而不是本机用户界面/视图。 Espresso 在这一领域表现出色,它提供了一组新的 Web 匹配器和 Web 断言,这些匹配器和断言有意与原生视图匹配器和视图断言相似。同时,它还包含基于 Web 技术的测试环境,提供了一种均衡的方法。

Espresso Web 建立在 WebDriver Atom 框架之上,用于查找和操作 Web 元素。Atom 类似于视图操作。Atom 将在网页内执行所有交互。WebDriver 公开了一组预定义的方法,如 findElement()getElement(),用于查找 Web 元素并返回相应的原子(在网页中执行操作)。

标准的 Web 测试语句如下所示,

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

这里,

  • onWebView() − 与 onView() 类似,它公开了一组 API 来测试 WebView。

  • withElement() − 使用 Atom 在网页内定位 Web 元素的几种方法之一,并返回 WebInteration 对象,类似于 ViewInteraction。

  • perform() − 使用 Atom 在网页内执行操作并返回 WebInteraction。

  • check() − 这使用 WebAssertion 执行必要的断言。

示例 Web 测试代码如下,

onWebView()
   .withElement(findElement(Locator.ID, "apple"))
   .check(webMatches(getText(), containsString("Apple")))

这里,

  • findElement() 定位一个元素并返回一个 Atom

  • webMatches 与 matches 方法类似

编写示例应用程序

让我们基于 WebView 编写一个简单应用程序,并使用 onWebView() 方法编写测试用例。按照以下步骤编写示例应用程序 −

  • 启动 Android Studio。

  • 按照前面讨论的方式创建新项目并将其命名为 MyWebViewApp

  • 使用 Refactor 将应用程序迁移到 AndroidX 框架 → 迁移AndroidX 选项菜单。

  • AndroidManifest.xml 文件中添加以下配置选项以授予访问 Internet 的权限。

<uses-permission android:name = "android.permission.INTERNET" />
  • Espresso web 作为单独的插件提供。因此,在 app/build.gradle 中添加依赖项并同步它。

dependencies {
   androidTestImplementation 'androidx.test:rules:1.1.1'
   androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.1'
}
  • 在主活动中移除默认设计并添加WebView。activity_main.xml内容如下,

<?xml version = "1.0" encoding = "utf-8"?>
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
   xmlns:app = "http://schemas.android.com/apk/res-auto"
   xmlns:tools = "http://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent"
   tools:context = ".MainActivity">
   <WebView
      android:id = "@+id/web_view_test"
      android:layout_width = "fill_parent"
      android:layout_height = "fill_parent" />
</RelativeLayout>
  • 创建一个新类 ExtendedWebViewClient,扩展 WebViewClient,并覆盖 shouldOverrideUrlLoading 方法,以在同一个 WebView 中加载链接操作;否则,它将在应用程序外部打开一个新的浏览器窗口。将其放在 MainActivity.java 中。

private class ExtendedWebViewClient extends WebViewClient {
   @Override
   public boolean shouldOverrideUrlLoading(WebView view, String url) {
      view.loadUrl(url);
      return true;
   }
}
  • 现在,在MainActivity的onCreate方法中添加以下代码。该代码的目的是找到WebView,对其进行适当的配置,然后最终加载目标url。

// 查找web view
WebView webView = (WebView) findViewById(R.id.web_view_test);

// 设置web view客户端
webView.setWebViewClient(new ExtendedWebViewClient());

// 清除缓存
webView.clearCache(true);

// 加载Url
webView.loadUrl("http://<your domain or IP>/index.html");

这里,

  • index.html的内容如下 −

<html>
   <head>
      <title>Android Web View Sample</title>
   </head>
   <body>
      <h1>Fruits</h1>
      <ol>
         <li><a href = "apple.html" id = "apple">Apple</a></li>
         <li><a href = "banana.html" id = "banana">Banana</a></li>
         </ol>
   </body>
</html>
  • index.html中引用的apple.html文件内容如下 −

<html>
   <head>
      <title>Android Web View Sample</title>
   </head>
   
   <body>
      <h1>Apple</h1>
   </body>
</html>
  • banana.html中引用的banana.html文件内容如下,

<html>
   <head>
      <title>Android Web View Sample</title>
   </head>
   
   <body>
      <h1>Banana</h1>
   </body>
</html>
  • 将 index.html、apple.html 和 banana.html 放置在 Web 服务器中

  • 将 loadUrl 方法中的 url 替换为您配置的 url。

  • 现在,运行应用程序并手动检查一切是否正常。以下是 WebView 示例应用程序 的屏幕截图 −

WebView Sample
  • 现在,打开 ExampleInstrumentedTest.java 文件并添加以下规则 −

@Rule
public ActivityTestRule<MainActivity> mActivityRule =
   new ActivityTestRule<MainActivity>(MainActivity.class, false, true) {
   @Override
   protected void afterActivityLaunched() {
      onWebView(withId(R.id.web_view_test)).forceJavascriptEnabled();
   }
};

在这里,我们找到了 WebView,并启用了 WebView 的 JavaScript,因为 espresso 网络测试框架专门通过 JavaScript 引擎来识别和操作网络元素。

  • 现在,添加测试用例来测试我们的 WebView 及其行为。

@Test
public void webViewTest(){
   onWebView()
      .withElement(findElement(Locator.ID, "apple"))
      .check(webMatches(getText(), containsString("Apple")))
      .perform(webClick())
      .withElement(findElement(Locator.TAG_NAME, "h1"))
      .check(webMatches(getText(), containsString("Apple")));
}

此处,测试按以下顺序进行:

  • 通过 findElement() 方法和 Locator.ID 枚举,使用其 id 属性找到链接 apple

  • 使用 webMatches() 方法检查链接的文本

  • 对链接执行点击操作。它打开 apple.html 页面。

  • 再次使用 findElement() 方法和 Locator.TAG_NAME 枚举找到 h1 元素。

  • 最后再次使用 webMatches() 方法检查 h1 标签的文本。

  • 最后,使用 android studio 上下文菜单运行测试用例。