默认情况下,Compose 测试会与界面同步。使用 ComposeTestRule
调用断言或操作时,测试将预先同步,直到界面树处于空闲状态。
通常,您无需执行任何操作。但是,您应该了解一些极端情况。
同步测试时,您可以使用虚拟时钟将 Compose 应用的时间提前。这意味着 Compose 测试不会实时运行,从而能够尽快通过测试。
但是,如果您不使用同步测试的方法,则不会发生任何重组,并且界面会暂停。
@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 界面同步。在某些情况下,您可能需要停止此同步并自行控制时钟。例如,您可以控制时间,以便在界面仍处于繁忙状态时对动画进行精确截图。如需停用自动同步功能,请将 mainClock
中的 autoAdvance
属性设置为 false
:
composeTestRule.mainClock.autoAdvance = false
一般情况下,您需要自行将时间提前。您可以使用 advanceTimeByFrame()
仅提前一帧,或使用 advanceTimeBy()
提前一段特定时间:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
空闲资源
Compose 可以同步测试和界面,以便以空闲状态完成各项操作和断言,从而根据需要等待或将时钟提前。但是,某些影响界面状态的异步操作可在后台运行,而测试无法得知这些结果。
在测试中创建并注册这些空闲资源,以便在确定受测应用是忙碌还是空闲时将这些资源考虑在内。除非需要注册其他空闲资源(例如,如果您运行的后台作业未与 Espresso 或 Compose 同步),否则无需执行任何操作。
此 API 与 Espresso 的空闲资源非常相似,用于指示受测对象是空闲还是忙碌。使用 Compose 测试规则注册 IdlingResource
的实现。
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
手动同步
在某些情况下,您必须将 Compose 界面与测试的其他部分或您测试的应用同步。
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:虽然 Espresso 适用于基于 View 的界面,但 Espresso 知识对于 Compose 测试的某些方面仍然很有帮助。