Espresso 在回收站视图中单击两个项目
Espresso click two items in recycler view
我想以这种方式对回收站视图的两个不同项目执行两次点击:
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
1,
longClick()
)
)
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
2,
longClick()
)
)
但我发现只有第二次点击位置 2 的项目才真正执行。
我还尝试了另一种变体:
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
1,
longClick()
),
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
2,
longClick()
)
)
但结果是一样的 - 只执行了第二次点击。
所以,问题是,我缺少什么以及如何正确实施这种情况?
感谢您的帮助!
更新。
似乎 initialTouchMode 标志不起作用。我用 initialTouchMode = true:
初始化我的 activity 测试规则
@get:Rule
var activityTestRule = ActivityTestRule(
ListActivity::class.java,
true,
false
)
然后在每个 @Test 方法中我调用 activityTestRule.launchActivity(Intent(Intent.ACTION_MAIN))
然后我点击。我发现,只有第一次点击不起作用,但第二次和第三次点击有效。那么,造成这种行为的原因是什么?
我找到问题的原因了。我的回收视图项目中有布局内部视图。这个视图实现了加载一些降价文本的 WebView。加载需要一些时间,所以我的点击是在视图真正呈现之前执行的。这是使测试工作的代码示例:
onView(withId(R.id.recycler_view))
.perform(
waitForMillis(1500),//wait until markdown views loaded
actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(1, longClick()),
actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(2, longClick())
)
其中 waitForMillis() 是自定义操作
fun waitForMillis(millis: Long): ViewAction? {
return object : ViewAction {
override fun getConstraints(): Matcher<View> {
return isDisplayed()
}
override fun getDescription(): String {
return "Wait for $millis milliseconds."
}
override fun perform(uiController: UiController, view: View) {
uiController.loopMainThreadForAtLeast(millis)
}
}
}
这个解决方案有缺点。为确保在单击之前渲染视图,您需要设置固定时间,这可能会比渲染真正需要的时间更长。所以最好的解决方案是自定义匹配器,但我现在没有现成的例子。
我想以这种方式对回收站视图的两个不同项目执行两次点击:
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
1,
longClick()
)
)
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
2,
longClick()
)
)
但我发现只有第二次点击位置 2 的项目才真正执行。
我还尝试了另一种变体:
onView(withId(R.id.recycler_view))
.perform(
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
1,
longClick()
),
RecyclerViewActions.actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(
2,
longClick()
)
)
但结果是一样的 - 只执行了第二次点击。
所以,问题是,我缺少什么以及如何正确实施这种情况?
感谢您的帮助!
更新。 似乎 initialTouchMode 标志不起作用。我用 initialTouchMode = true:
初始化我的 activity 测试规则@get:Rule
var activityTestRule = ActivityTestRule(
ListActivity::class.java,
true,
false
)
然后在每个 @Test 方法中我调用 activityTestRule.launchActivity(Intent(Intent.ACTION_MAIN)) 然后我点击。我发现,只有第一次点击不起作用,但第二次和第三次点击有效。那么,造成这种行为的原因是什么?
我找到问题的原因了。我的回收视图项目中有布局内部视图。这个视图实现了加载一些降价文本的 WebView。加载需要一些时间,所以我的点击是在视图真正呈现之前执行的。这是使测试工作的代码示例:
onView(withId(R.id.recycler_view))
.perform(
waitForMillis(1500),//wait until markdown views loaded
actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(1, longClick()),
actionOnItemAtPosition<CustomAdapter.CustomViewHolder>(2, longClick())
)
其中 waitForMillis() 是自定义操作
fun waitForMillis(millis: Long): ViewAction? {
return object : ViewAction {
override fun getConstraints(): Matcher<View> {
return isDisplayed()
}
override fun getDescription(): String {
return "Wait for $millis milliseconds."
}
override fun perform(uiController: UiController, view: View) {
uiController.loopMainThreadForAtLeast(millis)
}
}
}
这个解决方案有缺点。为确保在单击之前渲染视图,您需要设置固定时间,这可能会比渲染真正需要的时间更长。所以最好的解决方案是自定义匹配器,但我现在没有现成的例子。