web-dev-qa-db-ja.com

EspressoのRecyclerView内でアサートする方法は?

私はespresso-contribを使用してRecyclerViewでアクションを実行しています。

onView(withId(R.id.recycler_view))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); //click on first item

そして、私はそれについてアサーションを実行する必要があります。このようなもの:

onView(withId(R.id.recycler_view))
    .perform(RecyclerViewActions.actionOnItemAtPosition(0, check(matches(withText("Test Text"))));

しかし、 RecyclerViewActions はもちろんアクションを予期しているため、誤った2番目の引数タイプを示しています。 espresso-contribにはRecyclerViewAssertionsはありません。

リサイクラービューでアサーションを実行する方法はありますか?

43
juhlila

Danny Roaのソリューションを確認する必要があります Custom RecyclerView Actions そして、次のように使用します。

onView(withRecyclerView(R.id.recycler_view)
    .atPositionOnView(1, R.id.ofElementYouWantToCheck))
    .check(matches(withText("Test text")));
48
HowieH

とても簡単。追加のライブラリは必要ありません。行う:

_    onView(withId(R.id.recycler_view))
            .check(matches(atPosition(0, withText("Test Text"))));
_

viewHolderがViewGroupを使用している場合、withText()を次のようなhasDescendant()でラップします。

_onView(withId(R.id.recycler_view))
                .check(matches(atPosition(0, hasDescendant(withText("Test Text")))));
_

メソッドを使用すると、Utilsクラスに入れることができます。

_public static Matcher<View> atPosition(final int position, @NonNull final Matcher<View> itemMatcher) {
    checkNotNull(itemMatcher);
    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
        @Override
        public void describeTo(Description description) {
            description.appendText("has item at position " + position + ": ");
            itemMatcher.describeTo(description);
        }

        @Override
        protected boolean matchesSafely(final RecyclerView view) {
            RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position);
            if (viewHolder == null) {
                // has no item on such position
                return false;
            }
            return itemMatcher.matches(viewHolder.itemView);
        }
    };
}
_

最初にアイテムが画面に表示されない場合は、前にスクロールしてください:

_    onView(withId(R.id.recycler_view))
            .perform(scrollToPosition(87))
            .check(matches(atPosition(87, withText("Test Text"))));
_
80
riwnodennyk

Riwnodennykの答えを高めるために、ViewHolderViewGroupのような直接ViewオブジェクトではなくTextViewである場合、hasDescendantマッチャーを追加して、 TextView内のViewGroupオブジェクト。例:

onView(withId(R.id.recycler_view))
    .check(matches(atPosition(0, hasDescendant(withText("First Element")))));
24
You Qi

私の場合、Danny Roaとriwnodennykのソリューションをマージする必要がありました。

onView(withId(R.id.recyclerview))
.perform(RecyclerViewActions.scrollToPosition(80))
.check(matches(atPositionOnView(80, withText("Test Test"), R.id.targetview)));

およびメソッド:

public static Matcher<View> atPositionOnView(final int position, final Matcher<View> itemMatcher,
        @NonNull final int targetViewId) {

    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
        @Override
        public void describeTo(Description description) {
            description.appendText("has view id " + itemMatcher + " at position " + position);
        }

        @Override
        public boolean matchesSafely(final RecyclerView recyclerView) {
            RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
            View targetView = viewHolder.itemView.findViewById(targetViewId);
            return itemMatcher.matches(targetView);
        }
    };
}
5
Vince

私は同じ問題に苦労しており、6つのアイテムを持つリサイクラービューがあり、5番目のアイテムを選択しなければならず、5番目のビューはビューに表示されません。
上記のソリューションも機能します。また、少し遅れていることは知っていますが、共有する価値があると思いました。

以下の簡単なソリューションでこれを行いました:

onView(withId(R.id.recylcer_view))
    .perform(RecyclerViewActions.actionOnItem(
         hasDescendant(withText("Text of item you want to scroll to")), 
         click()));

RecyclerViewActions.actionOnItem-ViewActionと一致するビューでviewHolderMatcherを実行します。

  1. RecyclerViewに一致するビューまでitemViewMatcherをスクロールします
  2. 一致したビューでアクションを実行する

詳細については、以下を参照してください。 RecyclerViewActions.actionOnItem

5
Hiten Bahri

Danny Roaのソリューションは素晴らしいですが、スクロールしたばかりのオフスクリーンアイテムでは機能しませんでした。修正によりこれが置き換えられます。

View targetView = recyclerView.getChildAt(this.position)
                              .findViewById(this.viewId);

これとともに:

View targetView = recyclerView.findViewHolderForAdapterPosition(this.position)
                              .itemView.findViewById(this.viewId);

... TestUtilsクラス で。

1
I_AM_PANDA

このスレッドはかなり古いものですが、私は最近、RecyclerViewActionサポートをアサーションにも使用できるように拡張しました。これにより、ビューマッチャーを使用しながら、位置を指定せずに画面外の要素をテストできます。

この記事をご覧ください> Better Android RecyclerView Testing

1
Max Buster