【问题标题】:Finding views in a ViewPager using Espresso (AmbiguousViewMatcherException)使用 Espresso 在 ViewPager 中查找视图 (AmbiguousViewMatcherException)
【发布时间】:2017-06-23 17:45:06
【问题描述】:

我有一个 ViewPager,它一次只在屏幕上显示一个片段。该片段有一个 recyclerView,其中填充了由一个图像和两个 textView 组成的列表项。我需要选择项目并根据显示的文本执行单击。

我的 viewPage 的 ID 是 pager,recyclerView 是 listview,我正在使用 cardView 小部件,它有一个名为 cardContainer 的相对布局,它有一个我感兴趣的 textView nickNname

Espresso 似乎只能识别 pager,但它无法在视图层次结构中找到任何其他 Id。如何访问 nickName 或 viewPager 或片段中的任何其他视图?

我尝试了以下方法:

        ViewInteraction listviewInteraction = onView (allOf(withId(R.id.pager)));
    listviewInteraction.check(matches(hasDescendant(withId(R.id.listview))));

我收到以下错误,因为寻呼机没有任何孩子

    Expected: has descendant: with id: 2131689666
Got: "ViewPager{id=2131689659, res-name=pager, visibility=VISIBLE, width=1080, height=1533, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=144.0, child-count=0}"

我也尝试了一些不同的方法,类似于 here 发布的方法,但 Espresso 找不到 listviewnickname

如何找到视图nickName

更新:

我已经运行了更多测试,似乎 viewPager 在 Espresso 运行其测试时从未加载片段。我曾尝试使用Thread.sleep() 等待一段时间,但没有运气。我看到 listView 仅填充了一段时间,然后寻呼机变为空白并且测试失败,因为它找不到任何其他视图。知道是什么原因造成的吗?

更新 2:

寻呼机现在正常加载,但 Espresso 无法识别 listview 或 cardContainer,而只能识别寻呼机,因为 AmbiguousViewMatcherException。 viewPager 中有四个片段,但屏幕上只显示一个片段。我的代码如下:

ViewInteraction listviewInteraction = onView (allOf(withId(R.id.pager)));
    listviewInteraction.check(matches(isDisplayed()));
    onView(allOf(withId(R.id.listview), isDisplayed())).check(matches(isDisplayed()));

视图层次结构中有两个匹配项。如果我不使用 viewMatcher 中的 isDisplayed() 方法,那么我会得到四个片段的四个匹配项。我该如何解决?

【问题讨论】:

  • this 对您没有任何帮助吗?
  • 是的,这有帮助,我使用 isDisplayed() 并且屏幕外有一个列表视图,但 isCompletelyDisplayed() 修复了仅检测屏幕上的视图的问题。

标签: android listview android-fragments android-viewpager android-espresso


【解决方案1】:

屏幕外显然有一个列表视图,即使它不可见。匹配器isDisplayed() 还考虑了屏幕外的视图。使用isCompletelyDisplayed() 修复了AmbiguousViewMatcherException

【讨论】:

  • 谢谢。我们在 ViewPager 中有 4 个带有回收站视图的选项卡,这解决了问题。
【解决方案2】:

如果有人有兴趣在下面的机制中选择 TabByText

/**
 * Select Tab by [tabName] if it's available. Otherwise Throw PerformException
 */
fun selectTabByText(tabName: String, contains: Boolean = false, ignoreCase: Boolean = false): ViewAction {
    return object : ViewAction {
        override fun getDescription() = "With tab name $tabName"

        override fun getConstraints() = Matchers.allOf(isDisplayed(), ViewMatchers.isAssignableFrom(TabLayout::class.java))

        override fun perform(uiController: UiController, view: View) {
            val tabLayout = view as TabLayout
            val tabCount = tabLayout.tabCount
            for (tabIndex in 0 until tabCount) {
                /**
                 * Get the text of each available tab and if it's the same as [tabName]
                 * then select it
                 */
                val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabIndex)
                    ?: throw PerformException.Builder()
                        .withCause(Throwable("Tab at Index $tabIndex failed to be resolved to a Tab Object"))
                        .build()
                val tabText = tabAtIndex.text.toString()
                if (tabText.compare(tabName, ignoreCase, contains)) {
                    tabAtIndex.select()
                    return
                }
            }
            throw PerformException.Builder()
                .withCause(Throwable("Tab with name: $tabName with params: contains = $contains and ignoreCase = $ignoreCase is not found"))
                .build()
        }
    }
}

/**
 * Returns true if [contains] is true and this String contains the specified [other] String as a substring, optionally ignoring character case.
 * Returns true if [contains] is false and this string is equal to other, optionally ignoring character case.
 * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`.
 */
fun String.compare(other: String, ignoreCase: Boolean = false, contains: Boolean = false): Boolean =
    if (contains) {
        this.contains(other, ignoreCase = ignoreCase)
    } else

【讨论】:

    猜你喜欢
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多