等待WebView加载完成后再制作Espresso

32
有没有可靠的方法让Espresso等待WebView加载完成?
我尝试了这里提出的方法,但发现它不可靠。它还有其他缺点:
- 它依赖于替换WebView的WebChromeClient。任何现有的WebChromeClient也无法包装,因为WebViewrt出于某种原因没有getWebChromeClient()方法。 - 它需要一个特定的WebView实例,因此每次我启动一个带有WebView的Activity时,都必须获取WebView实例并为其注册一个新的WebviewIdlingResource。 - 我希望有人能够提供没有这些缺点的解决方案。我曾经希望espresso-web包可以提供解决方案,但似乎它没有提供任何与加载相关的内容。

我找到了这个:https://github.com/awslabs/aws-device-farm-sample-app-for-android/blob/a8aa3218fda2a0c72b039f371a1b5d12e522051f/app/src/androidTest/java/com/amazonaws/devicefarm/android/referenceapp/IdlingResources/WebViewIdlingResource.java - piotrek1543
WebView似乎有一个getWebChromeClient()方法。或许它是在原问题发布之后引入的。 - Michael Osofsky
2个回答

6
正如您所提到的,有一个名为espresso-web的Espresso插件可以处理Web视图及其内容。
“完成加载”是一个含糊不清的概念。这将取决于您要完成的具体内容。
如果您使用onWebView().check(<the you want to finish is in your webview>),那么只有在WebView加载完毕并且检查成功后,它才会返回。

Espresso-web是在Android上处理WebViews的入口点。它使用来自流行的WebDriver API的Atoms对WebView进行内省和控制其行为。

类似于onData,WebView交互实际上由几个View Atoms组成。Atom可以被视为ViewAction,即在您的UI中执行操作的自包含单元。但是,它们需要得到适当的协调并且相当冗长。Web和WebInteraction包装了这些样板,并给予与使用Espresso交互WebView的感觉。

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


1
那并没有回答问题。 - Krzysztof Kozmic
7
我已经有一段时间没有看过这个了,但如果我没记错的话,如果内容还没有加载完,check()会立即失败。换句话说,在调用它之前,我需要等待内容加载完成。 - vaughandroid
@vaughandroid说了什么? - Krzysztof Kozmic
1
@vaughandroid 我添加了一个超时,现在它会等待。 - Luis

0

如果使用WebChromeClient时遇到了 深入探究Espresso的Idling Resources 所描述的不可靠问题,考虑改用 WebViewClient

我发现当网页加载完成时,WebViewClient 可以可靠地触发 onPageFinished()WebChromeClientWebViewClient 相似,但 WebViewClient 更加通用,因为 WebChromeClient 处理 WebView 的 Chrome 特定方面(请参见 setWebViewClient与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实例才能完成此注册过程。一些开发人员可能会觉得在生产代码中添加CountingIdlingResourceincrement()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 项目可以依赖于一段代码来调用increment()/decrement(),每当任何异步 UI 事件开始/结束时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接