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

Android:如何在Espresso测试中操作MaterialDatePicker日期范围选择器?

解决方案

要在Espresso测试中完成MaterialDatePicker的日期范围选择,核心是定位日期选择器内的UI元素并执行操作,以下是具体实现步骤:

1. 基础操作流程

确保已触发日期选择器显示后,按以下步骤完成选择:

  • 定位并选择起始日期
  • 定位并选择结束日期
  • 点击确认按钮完成选择

2. 具体代码实现

适配Kotlin的日期选择工具方法

参考官方测试工具类逻辑,封装Kotlin方法来定位并选择指定日期:

import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem
import androidx.test.espresso.matcher.ViewMatchers.*
import org.hamcrest.Matcher
import java.util.*

/**
 * 选择指定UTC时间戳对应的日期
 */
fun selectDate(timestamp: Long) {
    val dayOfMonth = getDayOfMonthFromTimestamp(timestamp)
    // 定位日历RecyclerView,点击对应日期项
    onView(withId(com.google.android.material.R.id.mtrl_picker_calendar))
        .perform(
            actionOnItem<RecyclerView.ViewHolder>(
                hasDescendant(
                    allOf(
                        withId(com.google.android.material.R.id.mtrl_picker_day),
                        withText(dayOfMonth)
                    )
                ), click()
            )
        )
}

/**
 * 将UTC时间戳转换为当月日期字符串(如"15")
 */
private fun getDayOfMonthFromTimestamp(timestamp: Long): String {
    val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
        timeInMillis = timestamp
    }
    return calendar.get(Calendar.DAY_OF_MONTH).toString()
}

完整测试用例

结合你的业务场景,测试代码示例如下:

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import org.junit.Test

class YourFragmentTest {

    @Test
    fun testDateRangeSelection() {
        // 构造符合约束的UTC时间戳(示例为当前日期前后5天)
        val startDate = MaterialDatePicker.thisMonthInUtcMilliseconds() - 86400000 * 5
        val endDate = MaterialDatePicker.thisMonthInUtcMilliseconds() + 86400000 * 5
        val expectedStartDate = startDate.convertLongToDateString()
        val expectedEndDate = endDate.convertLongToDateString()

        // 1. 触发日期选择器显示
        onView(withId(R.id.textview)).perform(click())

        // 2. 等待选择器加载完成(验证标题可见)
        onView(withText("Select dates")).check(matches(isDisplayed()))

        // 3. 选择起始日期
        selectDate(startDate)

        // 4. 选择结束日期
        selectDate(endDate)

        // 5. 点击确认按钮
        onView(withText("OK")).perform(click())

        // 6. 验证结果(假设textview会显示选择的日期范围)
        onView(withId(R.id.textview)).check(matches(withText("$expectedStartDate - $expectedEndDate")))
    }
}

3. 额外场景处理

  • 切换月份:如果目标日期不在当前显示的月份,可通过切换按钮操作:
    // 切换到上一个月
    onView(withId(com.google.android.material.R.id.mtrl_picker_previous_button)).perform(click())
    // 切换到下一个月
    onView(withId(com.google.android.material.R.id.mtrl_picker_next_button)).perform(click())
    
  • 禁用日期校验:测试用例中使用的日期必须符合你设置的DateValidator规则,否则Espresso会抛出操作失败异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:47:03