How to count RecyclerView items with Espresso

后端 未结 7 1078
时光说笑
时光说笑 2020-12-25 09:49

Using Espresso and Hamcrest,

How can I count items number available in a recyclerView?

Exemple: I would like check if 5 items are displaying in a specific Re

相关标签:
7条回答
  • 2020-12-25 10:12

    Adding a bit of syntax sugar to the @Stephane's answer.

    public class RecyclerViewItemCountAssertion implements ViewAssertion {
        private final Matcher<Integer> matcher;
    
        public static RecyclerViewItemCountAssertion withItemCount(int expectedCount) {
            return withItemCount(is(expectedCount));
        }
    
        public static RecyclerViewItemCountAssertion withItemCount(Matcher<Integer> matcher) {
            return new RecyclerViewItemCountAssertion(matcher);
        }
    
        private RecyclerViewItemCountAssertion(Matcher<Integer> matcher) {
            this.matcher = matcher;
        }
    
        @Override
        public void check(View view, NoMatchingViewException noViewFoundException) {
            if (noViewFoundException != null) {
                throw noViewFoundException;
            }
    
            RecyclerView recyclerView = (RecyclerView) view;
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            assertThat(adapter.getItemCount(), matcher);
        }
    }
    

    Usage:

        import static your.package.RecyclerViewItemCountAssertion.withItemCount;
    
        onView(withId(R.id.recyclerView)).check(withItemCount(5));
        onView(withId(R.id.recyclerView)).check(withItemCount(greaterThan(5)));
        onView(withId(R.id.recyclerView)).check(withItemCount(lessThan(5)));
        // ...
    
    0 讨论(0)
  • 2020-12-25 10:12

    You can create a custom BoundedMatcher:

    object RecyclerViewMatchers {
        @JvmStatic
        fun hasItemCount(itemCount: Int): Matcher<View> {
            return object : BoundedMatcher<View, RecyclerView>(
                RecyclerView::class.java) {
    
                override fun describeTo(description: Description) {
                    description.appendText("has $itemCount items")
                }
    
                override fun matchesSafely(view: RecyclerView): Boolean {
                    return view.adapter.itemCount == itemCount
                }
            }
        }
    }
    

    And then use it like this:

    onView(withId(R.id.recycler_view)).check(matches((hasItemCount(5))))
    
    0 讨论(0)
  • 2020-12-25 10:15

    Based on @Sivakumar Kamichetty answer:

    1. Variable 'COUNT' is accessed from within inner class, needs to be declared final.
    2. Unnecessarily line: COUNT = 0;
    3. Transfer COUNT variable to one element array.
    4. Variable result is unnecessary.

    Not nice, but works:

    public static int getCountFromRecyclerView(@IdRes int RecyclerViewId) {
        final int[] COUNT = {0};
        Matcher matcher = new TypeSafeMatcher<View>() {
            @Override
            protected boolean matchesSafely(View item) {
                COUNT[0] = ((RecyclerView) item).getAdapter().getItemCount();
                return true;
            }
            @Override
            public void describeTo(Description description) {}
        };
        onView(allOf(withId(RecyclerViewId),isDisplayed())).check(matches(matcher));
        return COUNT[0];
    }
    
    0 讨论(0)
  • 2020-12-25 10:15

    I used the below method to get the count of RecyclerView

    public static int getCountFromRecyclerView(@IdRes int RecyclerViewId) {
    int COUNT = 0;
            Matcher matcher = new TypeSafeMatcher<View>() {
                @Override
                protected boolean matchesSafely(View item) {
                    COUNT = ((RecyclerView) item).getAdapter().getItemCount();
                    return true;
                }
                @Override
                public void describeTo(Description description) {
                }
            };
            onView(allOf(withId(RecyclerViewId),isDisplayed())).check(matches(matcher));
            int result = COUNT;
                COUNT = 0;
            return result;
        }
    

    Usage -

    int itemsCount = getCountFromRecyclerView(R.id.RecyclerViewId);
    

    Then perform assertions to check if the itemsCount is as expected

    0 讨论(0)
  • 2020-12-25 10:17

    Validated answer works but we can solve this problem with one line and without adapter awareness :

    onView(withId(R.id.your_recycler_view_id)).check(matches(hasChildCount(2)))
    

    Replace your_recycler_view_id with your id and 2 with the number to assert.

    0 讨论(0)
  • 2020-12-25 10:19

    To complete nenick answer and provide and little bit more flexible solution to also test if item cout is greaterThan, lessThan ...

    public class RecyclerViewItemCountAssertion implements ViewAssertion {
    
        private final Matcher<Integer> matcher;
    
        public RecyclerViewItemCountAssertion(int expectedCount) {
            this.matcher = is(expectedCount);
        }
    
        public RecyclerViewItemCountAssertion(Matcher<Integer> matcher) {
            this.matcher = matcher;
        }
    
        @Override
        public void check(View view, NoMatchingViewException noViewFoundException) {
            if (noViewFoundException != null) {
                throw noViewFoundException;
            }
    
            RecyclerView recyclerView = (RecyclerView) view;
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            assertThat(adapter.getItemCount(), matcher);
        }
    
    }
    

    Usage:

    onView(withId(R.id.recyclerView)).check(new RecyclerViewItemCountAssertion(5));
    onView(withId(R.id.recyclerView)).check(new RecyclerViewItemCountAssertion(greaterThan(5));
    onView(withId(R.id.recyclerView)).check(new RecyclerViewItemCountAssertion(lessThan(5));
    // ...
    
    0 讨论(0)
提交回复
热议问题