Утилизирую с помощью эспрессо, это ошибка? - PullRequest
0 голосов
/ 17 января 2020

Моя цель - тестирование прокрутки RecyclerView. Когда я выполняю примеры кодов, возникает эта ошибка:

E/TestRunner: androidx.test.espresso.PerformException: Error performing 'scroll RecyclerView to position: 17' on view 'with id: com.jakchang.hwahae:id/recyclerView'.
        at androidx.test.espresso.PerformException$Builder.build(PerformException.java:84)
       blabla ~~
     Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
    (is assignable from class: class androidx.recyclerview.widget.RecyclerView and is displayed on the screen to the user)
    Target view: "RecyclerView{id=2131296427, res-name=recyclerView, visibility=VISIBLE, width=1080, height=0, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@209ca0a, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=90.0, child-count=0}"

Я искал это, но не могу найти ничего, чтобы решить эту проблему. Вот мой код Помогите мне, пожалуйста

@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Rule
    @JvmField
    val mainActivity = ActivityTestRule(MainActivity::class.java)

    @Test
    fun useAppContext() {
        //mainActivity.launchActivity(Intent())

        Espresso.onView(ViewMatchers.withId(R.id.recyclerView)) 
            .perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(17))
        Thread.sleep(10000)
    }
}

1 Ответ

0 голосов
/ 20 января 2020

Согласно вашим журналам ошибок RecyclerView{..., child-count=0}, похоже, что ваше представление загружает данные асинхронно, и действие представления повторного вызова вызывается слишком рано. Самый простой способ исправить это, просто позвонив Thread.sleep(...) перед действием.

В качестве альтернативы вы можете использовать IdlingResource от Espresso в вашем тестовом примере:

fun waitUntil(matcher: Matcher<View>): ViewAction = object : ViewAction {

    override fun getConstraints(): Matcher<View> {
        return any(View::class.java)
    }

    override fun getDescription(): String {
        return StringDescription().let {
            matcher.describeTo(it)
            "wait until: $it"
        }
    }

    override fun perform(uiController: UiController, view: View) {
        if (!matcher.matches(view)) {
            ViewPropertyChangeCallback(matcher, view).run {
                try {
                    IdlingRegistry.getInstance().register(this)
                    view.viewTreeObserver.addOnDrawListener(this)
                    uiController.loopMainThreadUntilIdle()
                } finally {
                    view.viewTreeObserver.removeOnDrawListener(this)
                    IdlingRegistry.getInstance().unregister(this)
                }
            }
        }
    }
}

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

fun hasItemCount(itemCount: Matcher<Int>): Matcher<View> {
    return object : BoundedMatcher<View, RecyclerView>(RecyclerView::class.java) {
        override fun describeTo(description: Description) {
            description.appendText("has item count: ")
            itemCount.describeTo(description)
        }

        override fun matchesSafely(view: RecyclerView): Boolean {
            return view.adapter?.let {
                itemCount.matches(it.itemCount)
            } ?: false
        }
    }
}

Затем вы можете использовать действие и сопоставитель, чтобы подождать, пока ваш RecyclerView заполнится или будет готов:

onView(withId(R.id.recyclerView)).perform(
    waitUntil(hasItemCount(greaterThan(0))),
    RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(17)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...