是否有 Espresso 检查 BottomSheetBehavior 的状态?

Is there an Espresso check for the state of a BottomSheetBehavior?

在 Espresso 中有没有办法检查 BottomSheetBehavior 的状态?例如,我希望能够编写以下代码来检查附加到 myLayoutBottomSheetBehavior 是否具有状态 BottomSheetBehavior.STATE_COLLAPSED:

onView(withId(R.id.myLayout)).check(matches(hasBottomSheetBehaviorState(BottomSheetBehavior.STATE_COLLAPSED)))

是否有 LayoutBottomSheetBehavior 的 Espresso 匹配器?

我找不到现有的 Matcher 但能够编写一个似乎适用于这种情况的。这是 Kotlin 中的 hasBottomSheetBehaviorState

fun hasBottomSheetBehaviorState(expectedState: Int): Matcher<in View>? {
    return object : BoundedMatcher<View, View>(View::class.java) {
        override fun describeTo(description: Description) {
            description.appendText("has BottomSheetBehavior state $expectedState")
        }

        override fun matchesSafely(view: View): Boolean {
            val bottomSheetBehavior = BottomSheetBehavior.from(view)
            return expectedState == bottomSheetBehavior.state
        }
    }
}

添加到 Michael 的回答中,如果您的测试失败,可能有助于提供更友好的错误消息的一件事是将 Int 转换为用户友好消息的简单函数。

private fun getFriendlyBottomSheetBehaviorStateDescription(state: Int): String = when (state) {
    BottomSheetBehavior.STATE_DRAGGING -> "dragging"
    BottomSheetBehavior.STATE_SETTLING -> "settling"
    BottomSheetBehavior.STATE_EXPANDED -> "expanded"
    BottomSheetBehavior.STATE_COLLAPSED -> "collapsed"
    BottomSheetBehavior.STATE_HIDDEN -> "hidden"
    BottomSheetBehavior.STATE_HALF_EXPANDED -> "half-expanded"
    else -> "unknown but the value was $state"
}

fun hasBottomSheetBehaviorState(expectedState: Int): Matcher<in View>? {
    return object : BoundedMatcher<View, View>(View::class.java) {
        override fun describeTo(description: Description) {
            description.appendText("has BottomSheetBehavior state: ${getFriendlyBottomSheetBehaviorStateDescription(expectedState)}")
        }

        override fun matchesSafely(view: View): Boolean {
            val bottomSheetBehavior = BottomSheetBehavior.from(view)
            return expectedState == bottomSheetBehavior.state
        }
    }
}

然后,如果您要 运行 使用原始样本进行测试。

onView(withId(R.id.myLayout)).check(matches(hasBottomSheetBehaviorState(BottomSheetBehavior.STATE_COLLAPSED)))

它会输出以下内容,而不仅仅是一个数字。

Caused by: junit.framework.AssertionFailedError: 'has BottomSheetBehavior state: collapsed' doesn't match the selected view.

同样值得注意的是,使用以下方法确实需要创建一个空闲资源,以避免 espresso 在底部 sheet 行为未解决时尝试实现此断言。可能有更好的方法,但我使用 CountingIdlingResource 在底部 sheet 稳定和递减时对我的测试用例中有效的所有其他内容进行递增。

bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
       override fun onStateChanged(bottomSheet: View, newState: Int) {
            if (newState == BottomSheetBehavior.STATE_SETTLING) {
                countingIdlingResource.increment()
            } else {
                countingIdlingResource.decrement()
            }
        }

        override fun onSlide(bottomSheet: View, slideOffset: Float) {
        }
})