如何让Espresso点击特定的RecyclerView项目?

时间:2016-11-01 18:12:03

标签: android android-recyclerview android-espresso android-espresso-recorder

我正在尝试使用 Espresso 为我的Android应用编写一个使用RecyclerView的检测测试。这是主要布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/grid"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</android.support.design.widget.CoordinatorLayout>

...和项目视图布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>

这意味着屏幕上有几个TextViews,它们都有label个ID。我想点击一个特定的标签。我试着让Espresso测试记录器生成代码:

onView(allOf(withId(R.id.grid), isDisplayed()))
    .perform(actionOnItemAtPosition(5, click()));

我更愿意做类似的事情:

// Not working
onView(allOf(withId(R.id.grid), isDisplayed()))
    .perform(actionOnItem(withText("Foobar"), click()));

读数

我读了很多关于这个主题的内容,但仍然无法弄清楚如何根据内容 基于其位置索引测试RecyclerView项目。

2 个答案:

答案 0 :(得分:3)

您可以实施自定义RecyclerView匹配器。让我们假设你有RecyclerView,其中每个元素都有你想要匹配的主题:

public static Matcher<RecyclerView.ViewHolder> withItemSubject(final String subject) {
    Checks.checkNotNull(subject);
    return new BoundedMatcher<RecyclerView.ViewHolder, MyCustomViewHolder>(
            MyCustomViewHolder.class) {

        @Override
        protected boolean matchesSafely(MyCustomViewHolder viewHolder) {
            TextView subjectTextView = (TextView)viewHolder.itemView.findViewById(R.id.subject_text_view_id);

            return ((subject.equals(subjectTextView.getText().toString())
                    && (subjectTextView.getVisibility() == View.VISIBLE)));
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("item with subject: " + subject);
        }
    };
}

用法:

onView(withId(R.id.my_recycler_view_id)
    .perform(RecyclerViewActions.actionOnHolderItem(withItemSubject("My subject"), click()));

基本上你可以匹配你想要的任何东西。在此示例中,我们使用了主题TextView,但它可以是RecyclerView项中的任何元素。

要澄清的另一件事是检查可见性(subjectTextView.getVisibility() == View.VISIBLE)。我们需要拥有它,因为有时RecyclerView中的其他视图可能具有相同的主题,但它与View.GONE相同。这样我们就可以避免我们的自定义匹配器的多个匹配项和仅实现显示我们主题的目标项。

答案 1 :(得分:1)

actionOnItem()与ViewHolder的itemView匹配。在这种情况下,TextView包含在RelativeLayout中,因此您需要更新Matcher以对其进行说明。

onView(allOf(withId(R.id.grid), isDisplayed()))
    .perform(actionOnItem(withChild(withText("Foobar")), click()));

您还可以使用hasDescendant()来包装匹配器,例如更复杂的嵌套。