You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Espresso测试:利用Kotlin带接收者扩展函数简化重复代码

用Kotlin带接收者扩展函数简化Espresso RecyclerView测试代码

当然可以用Kotlin带接收者的扩展函数来简化这段重复的Espresso测试代码!我来给你一步步拆解实现:

先看你可能重复的代码场景

假设你现在的测试代码里,反复出现这样的逻辑(补全你给出的片段):

@Test
public void shouldSelectAll() {
    // 选中第0项并检查
    onView(withRecyclerView(R.id.multi_select_recycler))
        .perform(actionOnItemAtPosition(0, click()));
    onView(withRecyclerView(R.id.multi_select_recycler))
        .check(matches(hasDescendant(withText("Item 1").and(isSelected()))));
    
    // 选中第1项并检查
    onView(withRecyclerView(R.id.multi_select_recycler))
        .perform(actionOnItemAtPosition(1, click()));
    onView(withRecyclerView(R.id.multi_select_recycler))
        .check(matches(hasDescendant(withText("Item 2").and(isSelected()))));
    
    // 更多重复的选中+检查逻辑...
}

用带接收者扩展函数封装重复逻辑

我们可以针对**RecyclerView的资源ID(Int类型)**写带接收者的扩展函数,把选中和检查的逻辑封装起来:

// 封装:选中RecyclerView指定位置的项
fun Int.selectRecyclerViewItem(position: Int) {
    onView(withRecyclerView(this))
        .perform(actionOnItemAtPosition(position, click()))
}

// 封装:检查RecyclerView指定位置的项是否处于选中状态(匹配文本)
fun Int.checkRecyclerViewItemSelected(position: Int, itemText: String) {
    onView(withRecyclerView(this))
        .check(matches(hasDescendant(
            withText(itemText).and(isSelected())
        )))
}

// 如果需要更通用的匹配逻辑,还可以封装成接收自定义Matcher的版本
fun Int.checkRecyclerViewItemSelected(position: Int, itemMatcher: Matcher<View>) {
    onView(withRecyclerView(this))
        .check(matches(hasDescendantAtPosition(position, itemMatcher.and(isSelected()))))
}

简化后的测试代码

现在你的测试用例可以变得非常简洁,可读性也更强:

@Test
fun shouldSelectAll() {
    // 选中并检查第0项
    R.id.multi_select_recycler.selectRecyclerViewItem(0)
    R.id.multi_select_recycler.checkRecyclerViewItemSelected(0, "Item 1")
    
    // 选中并检查第1项
    R.id.multi_select_recycler.selectRecyclerViewItem(1)
    R.id.multi_select_recycler.checkRecyclerViewItemSelected(1, "Item 2")
    
    // 批量操作也很方便
    listOf(
        2 to "Item 3",
        3 to "Item 4"
    ).forEach { (position, text) ->
        R.id.multi_select_recycler.selectRecyclerViewItem(position)
        R.id.multi_select_recycler.checkRecyclerViewItemSelected(position, text)
    }
}

为什么用带接收者的扩展函数?

  • 语义化更强:R.id.multi_select_recycler.selectRecyclerViewItem(0) 读起来就像“让这个RecyclerView选中第0项”,逻辑一目了然。
  • 减少冗余:把重复的onView(withRecyclerView(...))逻辑全部封装,避免多次写相同的代码。
  • 可复用性高:这些扩展函数可以在所有测试类里复用,不用每次都写重复的Espresso调用。

内容的提问来源于stack exchange,提问作者Bohsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:23:33