如何在 Espresso 测试中等待视图消失?

问题描述 投票:0回答:3

我有一个

TextView
显示“正在加载”字符串,我需要等到该视图消失。我没有
Asynctask
的句柄,因为此方法在
IntentService
中运行,并在加载完成时发送广播。

知道如何在 Espresso 测试中等待视图状态的更改吗?我需要同样的一些字符串,这些字符串会改变并且需要等待。我以为是类似的呢

感谢您的帮助。网上的例子或常见问题解答并不多。

android android-espresso
3个回答
3
投票

您可以定义一个 ViewAction,每 50 毫秒(或您选择的不同时间)循环一次主线程,直到 View 的可见性更改为 View.GONE 或达到最大时间。

请按照以下步骤来实现此目的。

步骤1

定义ViewAction,如下:

/**
 * A [ViewAction] that waits up to [timeout] milliseconds for a [View]'s visibility value to change to [View.GONE].
 */
class WaitUntilGoneAction(private val timeout: Long) : ViewAction {

    override fun getConstraints(): Matcher<View> {
        return any(View::class.java)
    }

    override fun getDescription(): String {
        return "wait up to $timeout milliseconds for the view to be gone"
    }

    override fun perform(uiController: UiController, view: View) {

        val endTime = System.currentTimeMillis() + timeout

        do {
            if (view.visibility == View.GONE) return
            uiController.loopMainThreadForAtLeast(50)
        } while (System.currentTimeMillis() < endTime)

        throw PerformException.Builder()
            .withActionDescription(description)
            .withCause(TimeoutException("Waited $timeout milliseconds"))
            .withViewDescription(HumanReadables.describe(view))
            .build()
    }
}
步骤2

定义一个函数,在调用时创建此 ViewAction 的实例,如下所示:

/**
 * @return a [WaitUntilGoneAction] instance created with the given [timeout] parameter.
 */
fun waitUntilGone(timeout: Long): ViewAction {
    return WaitUntilGoneAction(timeout)
}
步骤3

在测试方法中调用此ViewAction,如下所示:

onView(withId(R.id.loadingTextView)).perform(waitUntilGone(3000L))
后续步骤

按照这个概念运行,并类似地创建一个

WaitForTextAction
类,该类等待 TextView 的文本更改为某个值。但是,在这种情况下,您可能需要将 getConstraints() 函数返回的 Matcher
any(View::class.java)
更改为
any(TextView::class.java)


2
投票

这个问题已经回答了这里

您可以通过使用 Espresso 为您的 Web 服务注册 IdlingResource 来处理这种情况。看看这篇文章

最有可能的是,您需要使用 CountingIdlingResource (它使用一个简单的计数器来跟踪某些东西何时空闲)。此示例测试演示了如何做到这一点。


1
投票

我是这样处理这个案例的:

public void waitForViewToDisappear(int viewId, long maxWaitingTimeMs) {
    long endTime = System.currentTimeMillis() + maxWaitingTimeMs;
    while (System.currentTimeMillis() <= endTime) {
        try {
            onView(allOf(withId(viewId), isDisplayed())).matches(not(doesNotExist()));
        } catch (NoMatchingViewException ex) {
            return; // view has disappeared
        }
    }
    throw new RuntimeException("timeout exceeded"); // or whatever exception you want
}

注意:

matches(not(doesNotExist()))
是一种“noop”匹配器;它只是为了确保
onView
部分真正运行。您同样可以编写一个不执行任何操作的
ViewAction
并将其包含在
perform
调用中,但这会增加更多行代码,因此我采用这种方式。

© www.soinside.com 2019 - 2024. All rights reserved.