簡體   English   中英

如何使用 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例如,使用方法assertItemCountIs(int)查看EspRecyclerView

@Stephane的答案中添加一些語法糖。

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

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

基於@Sivakumar Kamichetty回答:

  1. 變量'COUNT'是從內部類中訪問的,需要聲明為final。
  2. 不必要的行: COUNT = 0;
  3. COUNT變量傳遞給一個元素數組。
  4. 變量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];
}

我用下面的方法來獲取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是否符合預期

您可以創建自定義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
    ....
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM