0Pricing
Android Academy · 课时

使用 Espresso 进行 UI 测试

使用 Espresso 编写自动化 UI 测试。使用 onView() 查找视图,使用 perform() 进行交互,使用 check() 断言状态,并测试 RecyclerView 交互。

使用 Espresso 进行 UI 测试 是 CoddyKit 上的免费 Android Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 4 节课。

什么是 Espresso

Espresso 是 Android 官方的界面测试框架。它可以让您编写与应用界面交互的测试——点击按钮、输入文字、滚动列表——并断言屏幕上显示的内容。

Espresso 在设备或模拟器上运行(插桩测试),并会自动与界面线程同步,因此不需要使用容易导致测试不稳定的 sleep() 调用。

设置

Espresso 已包含在 Android 测试工具包中。将以下依赖项添加到 app/build.gradle:

// app/build.gradle:
android {
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1'  // RecyclerView
}

ActivityScenarioRule

使用 ActivityScenarioRule 在每次测试前启动 Activity,并在测试后将其关闭:

@RunWith(AndroidJUnit4::class)
class LoginActivityTest {

    @get:Rule
    val activityRule = ActivityScenarioRule(LoginActivity::class.java)

    @Test
    fun `login button is displayed`() {
        onView(withId(R.id.btnLogin))
            .check(matches(isDisplayed()))
    }
}

onView() 与 ViewMatchers

onView(matcher) 会在当前层次结构中查找视图。组合多个匹配器可以提高匹配精度:

// Match by ID:
onView(withId(R.id.tvTitle))

// Match by text:
onView(withText("Submit"))

// Match by content description (for accessibility):
onView(withContentDescription("Close dialog"))

// Combine matchers:
onView(allOf(withId(R.id.btnSave), isEnabled()))

// Inside a specific parent:
onView(withId(R.id.btnSave)).inRoot(isDialog())

ViewActions — 与视图交互

找到视图后,使用 .perform() 执行操作:

// Tap a button:
onView(withId(R.id.btnLogin)).perform(click())

// Type into an EditText:
onView(withId(R.id.etEmail))
    .perform(typeText("alice@example.com"), closeSoftKeyboard())

// Clear text and retype:
onView(withId(R.id.etPassword))
    .perform(clearText(), typeText("secret123"), closeSoftKeyboard())

// Scroll to a view:
onView(withId(R.id.btnSubmit)).perform(scrollTo(), click())

// Long press:
onView(withId(R.id.ivImage)).perform(longClick())

ViewAssertions — 验证状态

使用 .check() 检查屏幕上显示的内容:

// View is displayed:
onView(withId(R.id.tvError)).check(matches(isDisplayed()))

// View has specific text:
onView(withId(R.id.tvTitle)).check(matches(withText("Welcome!")))

// View is not displayed (GONE or INVISIBLE):
onView(withId(R.id.progressBar)).check(matches(not(isDisplayed())))

// View is enabled:
onView(withId(R.id.btnSave)).check(matches(isEnabled()))

// View does not exist:
onView(withId(R.id.tvError)).check(doesNotExist())

完整的登录测试

一个输入凭据并点击登录的完整测试:

@Test
fun `successful login shows home screen`() {
    // Type email
    onView(withId(R.id.etEmail))
        .perform(typeText("alice@example.com"), closeSoftKeyboard())

    // Type password
    onView(withId(R.id.etPassword))
        .perform(typeText("password123"), closeSoftKeyboard())

    // Tap login button
    onView(withId(R.id.btnLogin)).perform(click())

    // Assert welcome message is shown
    onView(withId(R.id.tvWelcome))
        .check(matches(withText("Welcome, Alice!")))
}

测试 RecyclerView

使用 espresso-contrib 中的 RecyclerViewActions 与列表项交互:

import androidx.test.espresso.contrib.RecyclerViewActions

@Test
fun `clicking item opens detail screen`() {
    // Scroll to position 5 and click:
    onView(withId(R.id.recyclerView))
        .perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
            5, click()
        ))

    // Assert detail screen is shown:
    onView(withId(R.id.tvDetailTitle)).check(matches(isDisplayed()))
}

测试输入验证

验证输入无效时是否显示错误消息:

@Test
fun `empty email shows error message`() {
    // Leave email blank, tap login
    onView(withId(R.id.btnLogin)).perform(click())

    // Assert error is shown
    onView(withId(R.id.tilEmail))
        .check(matches(hasDescendant(withText("Email is required"))))
}

@Test
fun `short password shows error`() {
    onView(withId(R.id.etPassword))
        .perform(typeText("123"), closeSoftKeyboard())
    onView(withId(R.id.btnLogin)).perform(click())
    onView(withId(R.id.tilPassword))
        .check(matches(hasDescendant(withText("Minimum 6 characters"))))
}

空闲资源

Espresso 会自动等待界面线程进入空闲状态,但不会等待网络调用或协程。使用 IdlingResource 告诉 Espresso 等待您的异步工作完成:

// CountingIdlingResource: increment before async work, decrement when done
val idlingResource = CountingIdlingResource("NetworkCall")

// In your ViewModel/Repository:
idlingResource.increment()
viewModelScope.launch {
    loadData()
    idlingResource.decrement()
}

// In test setUp:
@Before
fun setUp() {
    IdlingRegistry.getInstance().register(idlingResource)
}

@After
fun tearDown() {
    IdlingRegistry.getInstance().unregister(idlingResource)
}

运行 Espresso 测试

在已连接的设备或模拟器上运行插桩测试:

  • 在 Android Studio 中:右键点击测试类 → 运行
  • 通过终端:./gradlew connectedAndroidTest
  • 结果会显示在 app/build/reports/androidTests/ 中

使用 Android Emulator API 28 或更高版本,以获得稳定且快速的测试运行效果。在开发者设置中停用动画,避免测试不稳定。

快速检查

查找视图并检查其文本时,正确的 Espresso 模式是什么?

回顾:使用 Espresso 进行界面测试

自动化界面测试可以在用户发现问题之前捕获回归:

  • onView(matcher) — 查找视图
  • .perform(action) — 点击、输入和滚动
  • .check(matches(...)) — 断言可见性、文本和状态
  • 使用 RecyclerViewActions 与列表交互
  • 使用 IdlingResource 处理异步操作
  • 停用系统动画,避免测试不稳定

下一节:像专业人士一样调试和分析您的应用。

常见问题解答

「使用 Espresso 进行 UI 测试」课时是免费的吗?

是的 — 「使用 Espresso 进行 UI 测试」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 4 节课。

「使用 Espresso 进行 UI 测试」这节课中我会学到什么?

使用 Espresso 编写自动化 UI 测试。使用 onView() 查找视图,使用 perform() 进行交互,使用 check() 断言状态,并测试 RecyclerView 交互。 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Android Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「使用 Espresso 进行 UI 测试」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Android Academy 课中编写并运行代码吗?

能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 JUnit 进行单元测试
  2. 使用 Mockito 进行模拟
  3. 使用 Espresso 进行 UI 测试
  4. 调试与性能分析
← 返回 Android Academy