使用 Espresso 检查 RecyclerView 的每一项中的 TextView

Check TextView in each item of RecyclerView with Espresso

有一个 RecyclerView (R.id.recycler_view)。每个项目 (R.id.movie_card) 包含两个视图:ImageView 和 TextView (R.id.movie_title_text_view)。目标是与 Espresso 检查所有 recyclerview 的项目是否包含非空文本视图。请大家帮忙正确写代码

也有使用Idle。所以,开始测试RecyclerView的时刻是正确的(加载完所有数据后)。

不清楚如何断言所有 R.id.movie_title_text_view 都不为空。 完整测试方法如下:

@Rule
public ActivityTestRule activityTestRule = new ActivityTestRule(MainActivity.class);

@Test
public void GridFragmentRecycleViewTest(){
    final int TESTED_VIEWHOLDERS_QUANTITY = 10;

    IdlingResource componentIdlingResource = getIdlingResource();
    Espresso.registerIdlingResources(componentIdlingResource);
    Log.d(TAG, "GridFragmentRecycleViewTest()");
    onView(withId(R.id.action_search)).perform(click());
    onView(isAssignableFrom(SearchView.class)).perform(typeSearchViewText("lord")).perform(pressKey(KeyEvent.KEYCODE_ENTER));
    EspressoIdlingResource.increment();
    onView(withId(R.id.recycler_view)).check(new RecyclerViewItemCountAssertion(TESTED_VIEWHOLDERS_QUANTITY));

    //up to here all works good
    onView(allOf(withId(R.id.movie_title_text_view))).check(matches(withText(not(isEmptyString()))));
}

public static ViewAction typeSearchViewText(final String text){
    return new ViewAction(){
        @Override
        public Matcher<View> getConstraints() {
            //Ensure that only apply if it is a SearchView and if it is visible.
            return allOf(isDisplayed(), isAssignableFrom(SearchView.class));
        }

        @Override
        public String getDescription() {
            return "Change view text";
        }

        @Override
        public void perform(UiController uiController, View view) {
            ((SearchView) view).setQuery(text,false);
        }


    };
}

行:

onView(allOf(withId(R.id.movie_title_text_view))).check(匹配(withText(not(isEmptyString()))));

出现以下异常: androidx.test.espresso.AmbiguousViewMatcherException: '(with id: com.example.myapplication3:id/movie_title_text_view)' 匹配层次结构中的多个视图。 问题视图在下方标有“****匹配****”。

查看层次结构: +>DecorView{id=-1, visibility=VISIBLE, width=1440, height=2560, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false , is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) ty=BASE_APPLICATION wanim=0x10302f8 fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} ...

此答案尚未准备好使用,但如果您没有得到其他答案,它有望帮助您朝着正确的方向前进。

  1. 你需要依赖 RecyclerView 寻找 view holder 的能力,并构建 围绕它的断言 (RecyclerView.ViewHolder holder = recyclerViewInstance.findViewHolderForAdapterPosition(index);)
  2. 使用 holder.itemView.findViewsWithText(listOfViews, text, FIND_VIEWS_WITH_TEXT); 或例如 holder.itemView.findViewById(yourViewId);
  3. 查找相关的视图持有者视图
  4. 遍历您拥有的项目并为每个项目执行上述操作 项目

您可能希望为此目的构建一些视图断言:

    public static ViewAssertion hasViewWithXyzAtPosition(final int index, final CharSequence text) {
        return new ViewAssertion() {
            @Override
            public void check(View view, NoMatchingViewException e) {
                if (!(view instanceof RecyclerView)) {
                    throw e;
                }
                RecyclerView rv = (RecyclerView) view;
                RecyclerView.ViewHolder holder = rv.findViewHolderForAdapterPosition(index);

                //...

                Assert.assertTrue(
                        "There's no view at index " + index + ",
                        ...
                );
            }
        };
    }