LoginSignup
9
11

More than 5 years have passed since last update.

EspressoでRecyclerView内部のViewへのperformやcheckを行う方法

Posted at

EspressoでRecyclerViewの内部のViewに対してperformやcheckをしたかったので、そのときのworkaroundです。

次のようなMatcher用のメソッドを作ります。

    public static Matcher<View> withIdInRecyclerView(int id, int recyclerViewId, int position) {
        return allOf(ViewMatchers.withId(id), isDescendantOfRecyclerView(recyclerViewId, position));
    }

    public static Matcher<View> isDescendantOfRecyclerView(final int recyclerViewId, final int position) {
        return new BaseMatcher<View>() {
            @Override
            public boolean matches(Object arg) {
                if (arg instanceof View) {
                    View v = (View) arg;
                    View parent = v;
                    while (parent.getParent() != null && parent.getParent() instanceof View) {
                        if (parent.getId() == recyclerViewId && parent instanceof RecyclerView) {
                            RecyclerView.ViewHolder holder = findContainingViewHolder((RecyclerView) parent, v);
                            if (holder != null && holder.getAdapterPosition() == position) {
                                return true;
                            }
                        }
                        parent = (View) parent.getParent();
                    }
                }
                return false;
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("isDescendantOfRecyclerView(")
                        .appendValue(InstrumentationRegistry.getTargetContext().getResources().getResourceEntryName(recyclerViewId))
                        .appendText(",")
                        .appendValue(position)
                        .appendText(")");
            }
        };
    }

    /* このメソッドは最近のRecyclerViewには標準で実装されています。 */
    @Nullable
    public static RecyclerView.ViewHolder findContainingViewHolder(RecyclerView recyclerView, View view) {
        View v = view;
        while (v != null && v.getParent() instanceof View) {
            if (v.getParent() == recyclerView) {
                return recyclerView.getChildViewHolder(v);
            }
            v = (View) v.getParent();
        }
        return null;
    }

こうしておくと次のようにシンプルに書けます。

    int position = 123;
    onView(withId(R.id.recyclerview)).perform(scrollToPosition(position));
    onView(withIdInRecyclerView(R.id.button_hoge, R.id.recyclerview, position))
        .perform(click());
9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11