同步您的测试

Compose 测试默认情况下与您的 UI 同步。当您使用 ComposeTestRule 调用断言或操作时,测试将在之前同步,等待 UI 树空闲。

通常,您无需采取任何操作。但是,您应该了解一些边缘情况。

当测试同步时,您的 Compose 应用程序将使用虚拟时钟提前。这意味着 Compose 测试不会实时运行,因此它们可以尽快通过。

但是,如果您不使用同步测试的方法,则不会发生重新合成,UI 似乎会暂停。

@Test
fun counterTest() {
    val myCounter = mutableStateOf(0) // State that can cause recompositions.
    var lastSeenValue = 0 // Used to track recompositions.
    composeTestRule.setContent {
        Text(myCounter.value.toString())
        lastSeenValue = myCounter.value
    }
    myCounter.value = 1 // The state changes, but there is no recomposition.

    // Fails because nothing triggered a recomposition.
    assertTrue(lastSeenValue == 1)

    // Passes because the assertion triggers recomposition.
    composeTestRule.onNodeWithText("1").assertExists()
}

请注意,此要求仅适用于 Compose 层次结构,不适用于应用程序的其余部分。

禁用自动同步

当您通过 ComposeTestRule 调用断言或操作(例如 assertExists())时,您的测试会与 Compose UI 同步。在某些情况下,您可能希望停止此同步并自行控制时钟。例如,您可以控制时间以在 UI 仍然繁忙时对动画拍摄精确的屏幕截图。要禁用自动同步,请将 mainClock 中的 autoAdvance 属性设置为 false

composeTestRule.mainClock.autoAdvance = false

通常,您将自己推进时间。您可以使用 advanceTimeByFrame() 推进恰好一帧,或者使用 advanceTimeBy() 推进特定持续时间。

composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)

空闲资源

Compose 可以同步测试和 UI,以便每个操作和断言都在空闲状态下完成,根据需要等待或推进时钟。但是,一些异步操作的结果会影响 UI 状态,这些操作可以在测试没有意识到的情况下在后台运行。

在您的测试中创建并注册这些空闲资源,以便在决定被测应用程序是否繁忙或空闲时将它们考虑在内。除非您需要注册其他空闲资源,否则您无需采取任何措施,例如,如果您运行的后台作业与 Espresso 或 Compose 不同步。

此 API 与 Espresso 的 空闲资源 非常相似,用于指示被测主题是空闲还是繁忙。使用 Compose 测试规则来注册 IdlingResource 的实现。

composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)

手动同步

在某些情况下,您必须将 Compose UI 与测试的其他部分或您正在测试的应用程序同步。

waitForIdle() 函数等待 Compose 空闲,但该函数依赖于 autoAdvance 属性。

composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.

composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.

请注意,在这两种情况下,waitForIdle() 还会等待挂起的 绘制和布局过程

此外,您可以使用 advanceTimeUntil() 推进时钟,直到满足某个条件。

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

请注意,给定条件应检查可以受此时钟影响的状态(它仅适用于 Compose 状态)。

等待条件

任何依赖于外部工作的条件,例如数据加载或 Android 的测量或绘制(即,外部 Compose 的测量或绘制),都应使用更一般的概念,例如 waitUntil()

composeTestRule.waitUntil(timeoutMs) { condition }

您还可以使用任何 waitUntil 助手

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

其他资源

  • 在 Android 上测试应用程序:主要的 Android 测试登录页面提供了更广泛的测试基础和技术概述。
  • 测试基础了解有关测试 Android 应用程序的核心概念的更多信息。
  • 本地测试您可以在自己的工作站上本地运行一些测试。
  • 仪器测试最好也运行仪器测试。也就是说,直接在设备上运行的测试。
  • 持续集成持续集成可以让您将测试集成到您的部署管道中。
  • 测试不同的屏幕尺寸由于有许多设备可供用户使用,因此您应该测试不同的屏幕尺寸。
  • Espresso:虽然它适用于基于 View 的 UI,但 Espresso 知识仍然可以帮助您了解 Compose 测试的某些方面。