【问题标题】:Make Espresso wait for WebView to finish loading让 Espresso 等待 WebView 完成加载
【发布时间】:2015-11-11 06:27:19
【问题描述】:

有没有可靠的方法让 Espresso 等待 WebView 完成加载?

我已经尝试过here 概述的方法,但发现它不可靠。它还有其他缺点:

  • 它依赖于替换 WebView 的 WebChromeClient。任何现有的 WebChromeClient 也不能​​被包装,因为 WebViewrt 出于某种原因没有 getWebChromeClient() 方法。
  • 它需要一个特定的 WebView 实例,因此每次我使用 WebView 启动 Activity 时,我都必须获取 WebView 实例并为其注册一个新的 WebviewIdlingResource。

我希望有人能找到没有这些缺点的解决方案。我曾希望 espresso-web 包可以提供解决方案,但它似乎没有提供与加载相关的任何内容。

【问题讨论】:

标签: android testing webview android-espresso


【解决方案1】:

正如您所提到的,有一个名为 espresso-web 的 espresso 插件,用于处理 webview 及其内容。

“完成加载”是一个有点模糊的概念。这将取决于您想要完成的具体什么。

如果您使用onWebView().check(<the you want to finish is in your webview>),它只会在 Web 视图加载且 check 成功后返回。

Espresso-web 是在 Android 上使用 WebViews 的入口点。它使用流行的 WebDriver API 中的 Atom 来内省和控制 WebView 的行为。

和onData类似,WebView交互其实是由几个View Atom组成的。 Atom 可以看作是一个 ViewAction,一个在你的 UI 中执行操作的自包含单元。但是,它们需要经过适当的编排并且非常冗长。 Web 和 WebInteraction 封装了这个样板,并为与 WebView 交互提供了类似 Espresso 的感觉。

https://developer.android.com/training/testing/espresso/web

【讨论】:

  • 那没有回答问题
  • 我有一段时间没看这个了,但如果我没记错的话,如果内容还没有加载,check() 会立即失败。换句话说,我需要在调用它之前等待内容加载。
  • @vaughandroid 说了什么
  • @vaughandroid 我添加了一个超时,它等待。
【解决方案2】:

如果Wait for it...a deep dive into Espresso's Idling Resources 的不可靠性是由使用WebChromeClient 引起的,请考虑改用WebViewClient。

我发现当网页完成加载时WebViewClient 会可靠地触发onPageFinished()。 WebChromeClient 和 WebViewClient 相似,但 WebViewClient 更通用,因为 WebChromeClient 处理 WebView 的 Chrome 特定方面(请参阅 What's the difference between setWebViewClient vs. setWebChromeClient?)。

在示例项目https://github.com/mosofsky/how-to-coredux 中,我将onPageFinished() 函数注册到WebView,如下所示:

playVideoWebView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
        return false
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        if (null != url && url != ABOUT_URL) {
            // the next line dispatches an action that calls decrement()
            howToViewModel.dispatchAction(LoadVideo_Finish)
        }
    }
}

我希望这会有所帮助,尽管我承认我没有解决您提到的其他缺点。至于缺少getWebChromeClient(),现在好像可以了。至于需要特定的 WebView 实例,我不知道如何避免。不知何故,您必须让 WebView 在完成加载后减少空闲资源计数器。似乎任何解决方案都必须以某种方式接触 WebView 的特定实例才能完成此注册过程。一些开发人员可能会觉得用CountingIdlingResource 对increment() 和decrement() 的调用来乱扔他们的生产代码很乏味或不合适。

为了尽量减少使用空闲资源计数调用检测的代码量,您可以将这些调用隔离为我称之为异步代码的“副作用”。为此,我发现使用 Redux 数据存储非常有帮助,例如 CoRedux。当异步动作开始时,您可以将状态更新为“进行中”;当它结束时,清除“进行中”标志。 “副作用”可以是任何监听“进行中”的机制。 CoRedux 确实有一个称为“副作用”的构造,您可以使用它,但任何响应状态变化的机制都可以。

在how-to-coredux 示例项目的副作用中,它像这样调用increment() 和decrement():

when (action) {

    is Initialize_Start, is ShowVideoFragment_Start, LoadVideo_Start, HideVideoFragment_Start -> {
        espressoTestIdlingResource.increment()
    }

    Initialize_Finish, ShowVideoFragment_Finish, LoadVideo_Finish, HideVideoFragment_Finish -> {
        espressoTestIdlingResource.decrement()
    }
}

通过将空闲资源逻辑隔离为副作用,整个 Android 项目可以依赖于单个代码来分别在每次任何异步 UI 事件开始/结束时分别调用 increment()/decrement()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 2014-07-10
    • 2019-12-13
    • 1970-01-01
    相关资源
    最近更新 更多