使用 Espresso 在 ViewPager 中查找视图(AmbiguousViewMatcherException)
Finding views in a ViewPager using Espresso (AmbiguousViewMatcherException)
我有一个 ViewPager,一次只在屏幕上显示一个片段。此片段有一个 recyclerView,其中填充了由一个图像和两个 textView 组成的列表项。我需要 select 项目并根据显示的文本执行点击。
我的 viewPage 有 ID pager
,recyclerView 是 listview
,我正在使用 cardView 小部件,它有一个名为 cardContainer
的相对布局,它有一个 textView [=16] =] 我感兴趣的。
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 找不到 listview
或 nickname
.
如何找到视图 nickName
?
更新:
我还有 运行 几个测试,当 Espresso 运行 进行测试时,viewPager 似乎从不加载片段。我试过使用 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() 方法,那么我会得到四个片段的四个匹配项。我该如何解决?
屏幕外显然有一个列表视图,尽管它不可见。匹配器 isDisplayed()
还考虑了屏幕外的视图。使用 isCompletelyDisplayed()
修复了 AmbiguousViewMatcherException
.
如果有人对选择 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
我有一个 ViewPager,一次只在屏幕上显示一个片段。此片段有一个 recyclerView,其中填充了由一个图像和两个 textView 组成的列表项。我需要 select 项目并根据显示的文本执行点击。
我的 viewPage 有 ID pager
,recyclerView 是 listview
,我正在使用 cardView 小部件,它有一个名为 cardContainer
的相对布局,它有一个 textView [=16] =] 我感兴趣的。
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 找不到 listview
或 nickname
.
如何找到视图 nickName
?
更新:
我还有 运行 几个测试,当 Espresso 运行 进行测试时,viewPager 似乎从不加载片段。我试过使用 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() 方法,那么我会得到四个片段的四个匹配项。我该如何解决?
屏幕外显然有一个列表视图,尽管它不可见。匹配器 isDisplayed()
还考虑了屏幕外的视图。使用 isCompletelyDisplayed()
修复了 AmbiguousViewMatcherException
.
如果有人对选择 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