【问题标题】:Espresso - how to find a specific item in a recycler view (order is random)Espresso - 如何在回收站视图中找到特定项目(顺序是随机的)
【发布时间】:2021-01-19 00:22:19
【问题描述】:

我想知道如何在回收站视图中找到特定项目,每次运行时项目的顺序都是随机的。

假设我在回收站视图中有 4 个项目,每个项目都由相同类型的视图持有者表示,其中包含一个文本视图。一个唯一的标题被应用到每个视图持有者/项目。在这个例子中,为了简单起见,假设标题是“A”、“B”、“C”和“D”。

如果订单是随机的,我将如何找到位置(然后单击)项目“A”?我知道如果订单没有改变,我可以使用 scrollToPosition RecyclerViewInteraction 操作,但在这种情况下,订单可以并且将会改变。

有什么想法吗?

【问题讨论】:

  • 不要随机化项目,或者更确切地说,以可预测的方式随机化。您可以每次在随机生成器中使用相同的种子,以确保项目在您查找它们的位置。
  • 假设项目的顺序不能被开发者控制。在理想的世界中,是的,固定顺序(或您建议的可预测顺序)是理想的。对于这种情况,这是不可能的。

标签: android android-espresso


【解决方案1】:

我能够做到以下几点:

Matcher<RecyclerView.ViewHolder> matcher = CustomMatcher.withTitle("A");
onView((withId(R.id.recycler_view))).perform(scrollToHolder(matcher), actionOnHolderItem(matcher, click()));

CustomMatcher.withTitle 在哪里:

    public static Matcher<RecyclerView.ViewHolder> withTitle(final String title)
{
    return new BoundedMatcher<RecyclerView.ViewHolder, CustomListAdapter.ItemViewHolder>(CustomListAdapter.ItemViewHolder.class)
    {
        @Override
        protected boolean matchesSafely(CustomListAdapter.ItemViewHolder item)
        {
            return item.mTitleView.getText().toString().equalsIgnoreCase(title);
        }

        @Override
        public void describeTo(Description description)
        {
            description.appendText("view holder with title: " + title);
        }
    };
}

【讨论】:

  • 这只是因为CustomListAdapter.ItemViewHoldermTitleView 公开为公共字段。如果您只是为了测试而这样做,那么您将测试代码泄漏到应用程序中。
【解决方案2】:

您不需要自定义匹配器,只需使用它

onView(withId(R.id.recycler_id)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("A")), click()));

并添加 espresso-contrib 依赖项

    androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:<espressso-version>'

或者,如果您使用的是 AndroidX

    androidTestImplementation 'androidx.test.espresso:espresso-contrib:<espressso-version>'

【讨论】:

  • 当项目不在视图中时这将不起作用
  • 它会先滚动找到该项目然后点击它
  • 不为我滚动。
  • 我真的不敢相信这是我找到此信息的唯一地方。为什么这不是测试列表的默认方式:(
【解决方案3】:

我知道这是一个老问题,而 @Zach 的回答是一个好的开始,并在我的回答中帮助我,我们有一个回收者视图,其中包含大量不同类型的 ViewHolders,对于答案不完全适合的文本具有不同的 ID我们的用例。

我最终做的是使用稍微不同的匹配器,它不引用任何特定的 Id 或变量:

fun withText(title: String) = object : BoundedMatcher<View, View>(View::class.java) {
    override fun describeTo(description: Description?) {
        description?.appendText("Searching for title with: $title")
    }

    override fun matchesSafely(item: View?): Boolean {
        val views = ArrayList<View>()
        item?.findViewsWithText(views, title, View.FIND_VIEWS_WITH_TEXT)

        return when {
            views.size == 1 -> true
            else -> false
        }
    }
}

及用法:

RecyclerViewActions.scrollTo<ViewHolder>(withText("Some unique text I'm looking for")

【讨论】:

  • 非常有帮助。我不知道如何通过文本查找项目。
【解决方案4】:

通过自定义视图匹配器使用Espresso.onDataGoogle example

我使用了一些可以像这样适应你的情况的东西:

onData(new BaseMatcher<String>() {
        @Override
        public void describeTo(Description description) {
            // what?
            description.appendText("Matches A");
        }

        @Override
        public boolean matches(Object item) {
            return item instanceof String && ((String) item).equals("A");
        }
    }).perform(click());

如果模型类型比这更复杂,您可以用任何模型类型替换 String,如果模型类型简单,也可以使用内置匹配器(这种情况可以通过 onData(is("A")).perform(click()) 简化)。

【讨论】:

  • 听起来是个不错的方法,但尝试使用它时出错:android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: is assignable from class: class android.widget.AdapterView
  • 啊,我认为 onData 不能用于回收站视图,对吗?
  • 正确。我原以为它可能会奏效。不过有这个:stackoverflow.com/questions/27396583/…
  • 谢谢,这让我找到了处理它的方法......现在将在答案中发布!
猜你喜欢
  • 2022-10-15
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-02
相关资源
最近更新 更多