Эспрессо - Проверьте, что элементы RecyclerView упорядочены правильно - PullRequest
0 голосов
/ 10 октября 2018

Как проверить, отображаются ли элементы RecyclerView в правильном порядке с помощью Espresso?Я пытаюсь проверить это, проверяя текст по заголовку каждого элемента.

Когда я пробую этот фрагмент кода, он работает, чтобы щелкнуть по элементу, но не может перейти к щелчку, пытаясь установить текст для элемента

onView(withId(R.id.rv_metrics)).perform(actionOnItemAtPosition(0, click()));

Когда явместо этого попробуйте использовать пользовательское сопоставление. Я продолжаю получать сообщение об ошибке

Error performing 'load adapter data' on view 'with id: mypackage_name:id/rv_metrics'

Теперь я знаю onData doesn't work for RecyclerView, но до этого я пытался использовать настраиваемое сопоставление для этой задачи.

 public static Matcher<Object> hasTitle(final String inputString) {
    return new BoundedMatcher<Object, Metric>(Metric.class) {
        @Override
        protected boolean matchesSafely(Metric metric) {

            return inputString.equals(metric.getMetric());

        }

        @Override
        public void describeTo(org.hamcrest.Description description) {
            description.appendText("with title: ");
        }
    };
}

Я также попробовал что-то подобное, но это, очевидно, не работает из-за типа, заданного в качестве параметра для метода actionOnItemAtPosition, но будет ли у нас что-то похожее на это, которое может работать?

onView(withId(R.id.rv_metrics)).check(actionOnItemAtPosition(0, ViewAssertions.matches(withText("Weight"))));

Что мне здесь не хватает, пожалуйста?Большое спасибо.

Ответы [ 4 ]

0 голосов
/ 05 декабря 2018

Первоначальная проблема была решена, но я публикую здесь ответ, поскольку библиотека Barista решает эту проблему в одной одной строке кода .

assertDisplayedAtPosition(R.id.rv_metrics, 0, R.id.tv_title, "weight");

Он сделан поверх эспрессо, и документацию к нему можно найти здесь

Надеюсь, это кому-то может пригодиться.:)

0 голосов
/ 16 октября 2018

Если вы хотите сопоставить сопоставителя на позиции в RecyclerView, то вы можете попробовать создать пользовательский Matcher<View>:

public static Matcher<View> hasItemAtPosition(int position, Matcher<View> matcher) {
    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {

        @Override public void describeTo(Description description) {
            description.appendText("has item: ");
            matcher.describeTo(description);
            description.appendText(" at position: " + position);
        }

        @Override protected boolean matchesSafely(RecyclerView view) {
            RecyclerView.Adapter adapter = view.getAdapter();
            int type = adapter.getItemViewType(position);
            RecyclerView.ViewHolder holder = adapter.createViewHolder(view, type);
            adapter.onBindViewHolder(holder, position);
            return matcher.matches(holder.itemView);
        }
    };
}

И вы можете использовать его, например:

onView(withId(R.id.rv_metrics)).check(matches(0, hasDescendant(withText("Weight")))))
0 голосов
/ 14 ноября 2018

Я немного упростил ответ Мосиуса:

public static Matcher<View> hasItemAtPosition(final Matcher<View> matcher, final int position) {
    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
        @Override
        public void describeTo(Description description) {
            description.appendText("has item at position " + position + ": ");
            matcher.describeTo(description);
        }
        @Override
        protected boolean matchesSafely(RecyclerView recyclerView) {
            RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
            return matcher.matches(viewHolder.itemView);
        }
    };
}

Мы передаем Matcher функции, чтобы мы могли предоставить дополнительные условия.Пример использования:

onView(hasItemAtPosition(hasDescendant(withText("Item 1")), 0)).check(matches(isDisplayed()));
onView(hasItemAtPosition(hasDescendant(withText("Item 2")), 1)).check(matches(isDisplayed()));
0 голосов
/ 12 октября 2018

Как уже упоминалось, здесь , RecyclerView объекты работают не так, как AdapterView объекты, поэтому onData() нельзя использовать для взаимодействия с ними.

Для того, чтобы найтиДля просмотра в определенной позиции RecyclerView вам необходимо реализовать пользовательский RecyclerViewMatcher, как показано ниже:

public class RecyclerViewMatcher {
    private final int recyclerViewId;

    public RecyclerViewMatcher(int recyclerViewId) {
        this.recyclerViewId = recyclerViewId;
    }

    public Matcher<View> atPosition(final int position) {
        return atPositionOnView(position, -1);
    }

    public Matcher<View> atPositionOnView(final int position, final int targetViewId) {

        return new TypeSafeMatcher<View>() {
            Resources resources = null;
            View childView;

            public void describeTo(Description description) {
                String idDescription = Integer.toString(recyclerViewId);
                if (this.resources != null) {
                    try {
                        idDescription = this.resources.getResourceName(recyclerViewId);
                    } catch (Resources.NotFoundException var4) {
                        idDescription = String.format("%s (resource name not found)",
                                                      new Object[] { Integer.valueOf
                                                          (recyclerViewId) });
                    }
                }

                description.appendText("with id: " + idDescription);
            }

            public boolean matchesSafely(View view) {

                this.resources = view.getResources();

                if (childView == null) {
                    RecyclerView recyclerView =
                        (RecyclerView) view.getRootView().findViewById(recyclerViewId);
                    if (recyclerView != null && recyclerView.getId() == recyclerViewId) {
                        childView = recyclerView.findViewHolderForAdapterPosition(position).itemView;
                    }
                    else {
                        return false;
                    }
                }

                if (targetViewId == -1) {
                    return view == childView;
                } else {
                    View targetView = childView.findViewById(targetViewId);
                    return view == targetView;
                }

            }
        };
    }
}

И затем использовать его в своем тестовом примере следующим образом:

@Test
void testCase() {
    onView(new RecyclerViewMatcher(R.id.rv_metrics)
        .atPositionOnView(0, R.id.txt_title))
        .check(matches(withText("Weight")))
        .perform(click());

    onView(new RecyclerViewMatcher(R.id.rv_metrics)
        .atPositionOnView(1, R.id.txt_title))
        .check(matches(withText("Height")))
        .perform(click());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...