如何使用 Espresso 计算 RecyclerView 项目
How to count RecyclerView items with Espresso
使用 Espresso 和 Hamcrest,
如何计算 recyclerView 中可用的项目数?
示例:我想检查是否有 5 个项目显示在特定的 RecyclerView 中(必要时滚动)。
这里有一个 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 例如,参见 EspRecyclerView 方法 assertItemCountIs(int)
完成 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));
// ...
向 添加一点语法糖。
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);
}
}
用法:
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)));
// ...
我使用以下方法获取 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 是否符合预期
基于@Sivakumar Kamichetty 的回答:
- 从内部 class 访问变量 'COUNT',需要声明为最终变量。
- 不必要的行:
COUNT = 0;
- 将
COUNT
变量传送到一个元素数组。
- 不需要变量
result
。
不太好,但有效:
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];
}
您可以创建自定义 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))))
经过验证的答案有效,但我们可以在没有适配器感知的情况下用一行解决这个问题:
onView(withId(R.id.your_recycler_view_id)).check(matches(hasChildCount(2)))
将 your_recycler_view_id
替换为您的 ID,将 2
替换为要断言的号码。
使用 ActivityScenarioRule 计数
@get: Rule
val activityScenarioRule = ActivityScenarioRule(ShowListActivity::class.java)
@Test
fun testItemCount(){
activityScenarioRule.scenario.onActivity { activityScenarioRule ->
val recyclerView = activityScenarioRule.findViewById<RecyclerView(R.id.movieListRecyclerView)
val itemCount = recyclerView.adapter?.itemCount?:0
....
}
}
使用 Espresso 和 Hamcrest,
如何计算 recyclerView 中可用的项目数?
示例:我想检查是否有 5 个项目显示在特定的 RecyclerView 中(必要时滚动)。
这里有一个 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 例如,参见 EspRecyclerView 方法 assertItemCountIs(int)
完成 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));
// ...
向
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);
}
}
用法:
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)));
// ...
我使用以下方法获取 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 是否符合预期
基于@Sivakumar Kamichetty 的回答:
- 从内部 class 访问变量 'COUNT',需要声明为最终变量。
- 不必要的行:
COUNT = 0;
- 将
COUNT
变量传送到一个元素数组。 - 不需要变量
result
。
不太好,但有效:
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];
}
您可以创建自定义 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))))
经过验证的答案有效,但我们可以在没有适配器感知的情况下用一行解决这个问题:
onView(withId(R.id.your_recycler_view_id)).check(matches(hasChildCount(2)))
将 your_recycler_view_id
替换为您的 ID,将 2
替换为要断言的号码。
使用 ActivityScenarioRule 计数
@get: Rule
val activityScenarioRule = ActivityScenarioRule(ShowListActivity::class.java)
@Test
fun testItemCount(){
activityScenarioRule.scenario.onActivity { activityScenarioRule ->
val recyclerView = activityScenarioRule.findViewById<RecyclerView(R.id.movieListRecyclerView)
val itemCount = recyclerView.adapter?.itemCount?:0
....
}
}