android 如何点击Recycler查看特定位置View Visible- Espresso

vbkedwbf  于 2022-12-02  发布在  Android
关注(0)|答案(1)|浏览(183)

bounty将在3天后过期。回答此问题可获得+50声望奖励。Nayab希望吸引更多人关注此问题。

我正在使用Espresso为我的应用程序编写UI测试。屏幕显示了一个Recyclerview,其中包含状态为OPENCLOSED的商店列表。根据数据的不同,openTextViewclosedTextview会显示,默认情况下会隐藏。

以下是我的测试案例场景:

  • 检查屏幕是否可见
  • 检查回收视图是否可见
  • 检查Recyclerview是否至少有一个商店的状态为OPEN
  • 点击第一个找到OPEN店铺
  • 检查详细信息屏幕是否显示
    版本:

我尝试单击第一个OPEN状态项,但它抛出了异常。
下面是代码

@Test
fun openShopTest() {

    onView(withText(“Shops")).check(matches(isDisplayed()))

    onView(withId(R.id.rvShops)).check(matches(isDisplayed()))

    //There is at least one open shop visible

    onView(withId(R.id.rvShops))
        .perform(RecyclerViewActions.scrollToHolder(first(withOpenText())))

    //User clicks on open shop

    onView(allOf(withId(R.id.rvShops), isDisplayed()))
        .perform(actionOnItem<ListAdapter.ListViewHolder>(withChild(withText(“Open”)), click()))

    //Screen with details appear

    onView(withText("Details”)).check(matches(isDisplayed()))

}

fun withOpenText(): Matcher<RecyclerView.ViewHolder> {
    return object :
        BoundedMatcher<RecyclerView.ViewHolder, ListAdapter.ListViewHolder>(
            ListAdapter.ListViewHolder::class.java
        ) {

        override fun describeTo(description: Description) {
            description.appendText("No ViewHolder found with Open Status Visible")
        }

        override fun matchesSafely(item: ListAdapter.ListViewHolder): Boolean {
            val openTextView = item.itemView.findViewById(R.id.openTextView) as TextView
            return openTextView.isVisible
        }
    }
}

以下是例外情况:

androidx.test.espresso.PerformException: Error performing 'performing ViewAction: single click on item matching: holder with view: has child: with text: is "Open"' on view '(with id: mypackagename:id/rvShops and is displayed on the screen to the user)'.
at androidx.test.espresso.PerformException$Builder.build(PerformException.java:82)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:79)
at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:51)
at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:312)
at androidx.test.espresso.ViewInteraction.desugaredPerform(ViewInteraction.java:173)
at androidx.test.espresso.ViewInteraction.perform(ViewInteraction.java:114)
at mypackagename.MyUITest.openShopTest(MyUITest.kt:77)
... 32 trimmed
Caused by: androidx.test.espresso.PerformException: Error performing 'scroll RecyclerView to: holder with view: has child: with text: is "Open"' on view 'RecyclerView{id=2131231032, res-name=rvShops, visibility=VISIBLE, width=1080, height=2047, 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=androidx.constraintlayout.widget.ConstraintLayout$LayoutParams@295fec9, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=12}'.
at androidx.test.espresso.PerformException$Builder.build(PerformException.java:82)
at androidx.test.espresso.contrib.RecyclerViewActions$ScrollToViewAction.perform(RecyclerViewActions.java:381)
at androidx.test.espresso.contrib.RecyclerViewActions$ActionOnItemViewAction.perform(RecyclerViewActions.java:221)
at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:356)
at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:248)
at androidx.test.espresso.ViewInteraction.access$100(ViewInteraction.java:63)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:153)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:150)
at java.util.concurrent.FutureTask.run(FutureTask.java:264)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.RuntimeException: Found 0 items matching holder with view: has child: with text: is "Open", but position -1 was requested.
at androidx.test.espresso.contrib.RecyclerViewActions$ScrollToViewAction.perform(RecyclerViewActions.java:361)

"我尝试过什么"

  • 我有一个想法,也许openTextViewclosedTextview并不总是可见的,所以这可能是造成的问题。我尝试使两者始终可见以及。
  • 我按照this question的答案中提到的步骤操作,但出现了同样的异常。
    需要什么?
  • 单击显示openTextView的Recycler查看行
  • 获取openTextView可见的行的位置;这样我就可以使用atPosition函数并单击该行。

有人能帮我吗?
任何帮助都将不胜感激。
谢谢

cyej8jka

cyej8jka1#

我们的想法是自定义Espresso的View操作。

object MyViewAction {
    fun clickChildViewWithIdAndText(id: Int, text: String): ViewAction {
        return object: ViewAction {
            override fun getConstraints(): Matcher<View> {
                return withText(text)
            }

            override fun getDescription(): String {
                return "Click on a child view with specified id and text"
            }

            override fun perform(uiController: UiController?, view: View) {
                val v: View = view.findViewById(id)
                v.performClick()
            }
        }
    }
}

onView(withId(R.id.rv_home)).perform(
      RecyclerViewActions.actionOnItemAtPosition<ListAdapter.ListViewHolder>(
          0,
          MyViewAction.clickChildViewWithIdAndText(R.id.tv_id, "OPEN")
      )
);

顺便说一句,你可以使用一些强大的测试库,这些库是建立在Espresso之上的,比如BaristaKakao
例如,只需一行代码,就可以Assert列表视图中显示在位置x且带有文本y的项

import com.adevinta.android.barista.assertion.BaristaListAssertions.assertDisplayedAtPosition

assertDisplayedAtPosition(R.id.rv_list, x, R.id.tv_id, y)

相关问题