Kakao/Kaspresso 在 RecyclerView 中与不同 ViewType 匹配

问题描述 投票:0回答:2

我在使用 Kakao 的 UI 测试中操作具有不同 ViewType 的 RecyclerView 时遇到问题:

RecyclerView 用于自动完成器,有两种 ViewType:

  1. 常规结果(auto_completer_item_root)
  2. 附近搜索的特殊项目(gps_search_item_root)

我想要实现的目标:单击 RecyclerView 中的第一个项目,该项目具有与我的“常规”项目匹配的视图。注意:RecyclerView 中的第一个项目没有此类型,而是上面提到的“特殊项目”类型。

视图 xml 如下所示:

<androidx.constraintlayout.widget.ConstraintLayout 
    ...
    android:id="@+id/auto_completer_item_root" ...>

    <TextView
        android:id="@+id/destination_title"
        ...
    />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout 
    ...
    android:id="@+id/gps_search_item_root" ...>

    <TextView
        android:id="@+id/gps_title"
        ...
    />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

我有一个 RecyclerView 的屏幕对象:

class AutoCompleterScreen : KScreen<AutoCompleterScreen>() {

    override val layoutId: Int? = null
    override val viewClass: Class<*>? = null

    val resultList = KRecyclerView(
        builder = { withId(R.id.destinationList) },
        itemTypeBuilder = {
            itemType(::GpsSearch)
            itemType(::AutoCompleterResult)
        }
    )

    internal class AutoCompleterResult(parent: Matcher<View>) : KRecyclerItem<AutoCompleterResult>(parent) {
        val title: KTextView = KTextView(parent) { withId(R.id.destination_title) }
    }

    internal class GpsSearch(parent: Matcher<View>) : KRecyclerItem<GpsSearch>(parent) {
        val title: KTextView = KTextView(parent) { withId(R.id.gps_title) }
    }
}

我在测试中尝试了不同的方法,我希望这会起作用:

onScreen<AutoCompleterScreen> {
    resultList {
        firstChild<AutoCompleterScreen.AutoCompleterResult> {
            title {
                click()
            }
        }
    }
}

但事实并非如此。

我不断试验,这个成功了一次,但我无法重复,所以这可能与应用程序没有新安装有关:

onScreen<AutoCompleterScreen> {
    resultList {
        childWith<AutoCompleterScreen.AutoCompleterResult> {
            withId(R.id.auto_completer_item_root)
            isFirst()
        } perform {
            click()
        }
    }
}

另一方面,我设法想出了一些实际有效的 Espresso 代码 - 但当我使用 Kaspresso 时,我想学习如何利用该框架:

onView(withId(R.id.destinationList))
  .perform(actionOnFirstItemWithId(R.id.auto_completer_item_root, click()))

使用

fun actionOnFirstItemWithId(@IdRes viewId: Int, action: ViewAction): ViewAction {

    return object : ViewAction {
        override fun getConstraints(): Matcher<View> {
            return Matchers.allOf(ViewMatchers.isAssignableFrom(RecyclerView::class.java), ViewMatchers.isDisplayed())
        }

        override fun getDescription(): String {
            return "Perform action on the first item that has a view with the given ID."
        }

        override fun perform(uiController: UiController, view: View) {
            val recyclerView = view as RecyclerView
            for (i in 0 until recyclerView.adapter!!.itemCount) {
                uiController.loopMainThreadForAtLeast(500)
                val viewHolder = recyclerView.findViewHolderForAdapterPosition(i)
                if (viewHolder?.itemView?.findViewById<View>(viewId) != null) {
                    if (i != 0) {
                        recyclerView.scrollToPosition(i)
                        uiController.loopMainThreadForAtLeast(500)
                    }
                    val targetView = viewHolder.itemView.findViewById<View>(viewId)
                    action.perform(uiController, targetView)
                    return
                }
            }
        }
    }
}

也许,Kakao/Kaspresso 在主线程循环方面存在问题,但由于其内部的 flakysafe 实现,它应该支持没有循环的问题。

有人可以帮助我使用 Kakao/Kaspresso 吗?

android android-recyclerview android-espresso kakao
2个回答
0
投票

您能否在失败的运行期间也发送 Kaspresso 的日志?我可能也有类似的问题,但如果没有看到它在哪里失败,我不能肯定地说。


0
投票

其实就是代码

onScreen<AutoCompleterScreen> {
    resultList {
        childWith<AutoCompleterScreen.AutoCompleterResult> {
            withId(R.id.auto_completer_item_root)
            isFirst()
        } perform {
            click()
        }
    }
}

有两个缺陷:

a)

auto_completer_item_root
似乎不是 RecyclerView 项目的一部分,我需要将其与
destination_title
交换。最后,我什至可以删除
withId
检查,因为 Kakao 使用
childWith
进行了该检查。

b) 在我的场景中,RecyclerView 预先填充了先前搜索的数据,这意味着符合上述条件的项目已经在 RecyclerView 中,但在 RecyclerView 使用当前运行的更新更新之前,并不打算单击它们搜索(在测试的早期发布)。因此,我需要添加一个检查,以确保搜索结果适合当前关键字。

这是工作代码:

onScreen<AutoCompleterScreen> {
    resultList {
        childWith<AutoCompleterScreen.AutoCompleterResult> {
            containsText("current keyword")
            isFirst()
        } perform {
            click()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.