如何使用Espresso计算RecyclerView项目

时间:2016-04-04 10:07:55

标签: android android-recyclerview android-espresso hamcrest

使用Espresso和Hamcrest,

如何计算recyclerView中可用的项目编号?

例子:我想检查特定的RecyclerView中是否有5个项目显示(必要时滚动)。

7 个答案:

答案 0 :(得分:72)

这里有一个示例ViewAssertion来检查RecyclerView项目计数

public class RecyclerViewItemCountAssertion implements ViewAssertion {
  private final int expectedCount;

  public RecyclerViewItemCountAssertion(int expectedCount) {
    this.expectedCount = expectedCount;
  }

  @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(), is(expectedCount));
  }
}

然后使用此断言

onView(withId(R.id.recyclerView)).check(new RecyclerViewItemCountAssertion(5));

我已经开始编写一个库,可以使用espresso和uiautomator使测试变得更简单。这包括RecyclerView操作和断言的工具。 https://github.com/nenick/espresso-macchiato例如使用方法assertItemCountIs(int)参见EspRecyclerView

答案 1 :(得分:26)

@Stephane's answer添加一些语法糖。

colorPrimary

用法:

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);
    }
}

答案 2 :(得分:17)

要完成nenick的答案,并提供更灵活的解决方案,以测试项目cout是否更大,更少,但是...

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);
    }

}

用法:

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));
// ...

答案 3 :(得分:6)

基于@Sivakumar Kamichetty回答:

  1. 从内部类中访问变量'COUNT',需要声明为final。
  2. 不必要的行:COUNT = 0;
  3. COUNT变量转移到一个元素数组。
  4. 变量result是不必要的。
  5. 不好,但有效:

    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];
    }
    

答案 4 :(得分:5)

我使用以下方法获取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;
    }

用法 -

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

然后执行断言以检查itemsCount是否符合预期

答案 5 :(得分:1)

您可以创建自定义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
            }
        }
    }
}

然后像这样使用它:

onView(withId(R.id.recycler_view)).check(matches((hasItemCount(5))))

答案 6 :(得分:1)

有效的答案是可行的,但是我们只需一行就可以解决此问题,而无需了解适配器:

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

用您的ID替换your_recycler_view_id,用要声明的数字替换2