Android Studio 运行 录制 Espresso 测试失败

AndroidStudio Running Recorded Espresso Test fails

我正在尝试在 AndroidStudio 4.2 中录制浓缩咖啡测试。录音似乎工作正常。但是,当我尝试 运行 记录的测试时,他们 运行 大约在中途出现 activity 开关,然后它失败了,因为找不到视图并且我不断得到 NoMatchingViewException.

我在第一个 activity 中进行了一系列点击,这触发了第二个 activity 的加载。当 运行 试图在第二个 activity 中找到视图的测试永远不起作用。

@Test
fun firstRecordedTest() {
    val materialButton = onView(
        allOf(
            withId(R.id.key1Button), withText("1"),
            childAtPosition(
                childAtPosition(
                    withClassName(`is`("android.widget.LinearLayout")),
                    0
                ),
                3
            ),
            isDisplayed()
        )
    )
    materialButton.perform(click())
    
    // Activity switches here
    // The following never works

    val matcher: Matcher<View> = allOf(
        withId(R.id.tab_contacts), withContentDescription("Contacts"),
        childAtPosition(
            childAtPosition(
                withId(R.id.navigation_view),
                0
            ),
            1
        ),
        isDisplayed()
    )
    val bottomNavigationItemView = onView(matcher)
    bottomNavigationItemView.perform(click())
    
}

我曾尝试放置不同种类的计时器等来等待视图加载,但要么卡住,要么失败。我也试过 this answer 但没有成功。

我错过了什么吗?是不是espresso刻录机允许,切换后无法继续测试activity?

Espresso 有时会因景色而变幻莫测。您是否尝试使用第二个 activity 中的另一个视图或删除导致测试失败的视图和 运行 没有它的测试?

浓缩咖啡不需要定时器。它会等到 activity 完全加载,你可以阅读它 here

其次,我自己没有用过录音机,因为它会产生很多噪音。例如下面的代码

val matcher: Matcher<View> = allOf(
        withId(R.id.tab_contacts), withContentDescription("Contacts"),
        childAtPosition(
            childAtPosition(
                withId(R.id.navigation_view),
                0
            ),
            1
        ),
        isDisplayed()
    )

我在这里假设点击了 navigation_view 中的一个按钮。 可以简单地替换为

onView(withId(R.id.tab_contacts)).perform(click())

现在,关于您的测试失败的原因,似乎 materialButton 点击正在执行一些异步工作或执行某种动画。 您可以像这样

在 build.gradle 中禁用动画
android {
    ...
    testOptions {
        animationsDisabled = true
    }
    ...
}

如果您阅读 here,我总结一下,espresso 应该等待执行任何操作(在您的情况下,单击 tab_contacts),直到消息队列为空,它会与异步任务也是如此,但是 espresso 不知道其他异步长 运行 操作。所以,如果你正在使用一些异步操作,你应该考虑使用空闲资源来进行可靠的测试。

但如果您想快速破解,可以使用这种睡眠方法:

    private fun sleep(millis: Long): ViewAction {
        return object : ViewAction {
            override fun getConstraints(): Matcher<View> {
                return isRoot()
            }

            override fun getDescription(): String {
                return "Going to sleep for " + millis + "milliseconds"
            }

            override fun perform(uiController: UiController, view: View) {
                uiController.loopMainThreadForAtLeast(millis)
            }
        }
    }

然后像这样调用上面的方法:

    onView(isRoot())
                .perform(sleep(
                        TimeUnit.SECONDS.toMillis(10)
                ))