您可以使用既定的方法和模式测试您的 Compose 应用。
隔离测试
ComposeTestRule
允许您启动一个显示任何可组合项的 Activity:您的完整应用、单个屏幕或一个小型元素。检查您的可组合项是否正确封装且独立工作也是一个好习惯,这有助于更轻松、更专注于 UI 测试。
这并不意味着您应该只创建单元 UI 测试。范围涵盖 UI 较大部分的 UI 测试也非常重要。
设置自己的内容后访问 Activity 和资源
通常,您需要使用 composeTestRule.setContent
设置要测试的内容,并且还需要访问 Activity 资源,例如断言显示的文本与字符串资源匹配。但是,如果 Activity 已经调用了 setContent
,则您无法在使用 createAndroidComposeRule()
创建的规则上调用 setContent
。
实现此目的的常见模式是使用空 Activity(例如 ComponentActivity
)创建 AndroidComposeTestRule
。
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
请注意,ComponentActivity
需要添加到您的应用 AndroidManifest.xml
文件中。通过将此依赖项添加到您的模块来启用此功能
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
自定义语义属性
您可以创建自定义语义属性,以向测试公开信息。为此,请定义新的 SemanticsPropertyKey
并使用 SemanticsPropertyReceiver
使其可用。
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
现在在 semantics
修饰符中使用该属性
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
在测试中,使用 SemanticsMatcher.expectValue
断言属性的值
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
验证状态恢复
验证您的 Compose 元素的状态在 Activity 或进程重新创建时是否正确恢复。使用 StateRestorationTester
类执行此类检查,而无需依赖 Activity 重新创建。
此类允许您模拟可组合项的重新创建。它对于验证 rememberSaveable
的实现特别有用。
class MyStateRestorationTests {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun onRecreation_stateIsRestored() {
val restorationTester = StateRestorationTester(composeTestRule)
restorationTester.setContent { MainScreen() }
// TODO: Run actions that modify the state
// Trigger a recreation
restorationTester.emulateSavedInstanceStateRestore()
// TODO: Verify that state has been correctly restored.
}
}
测试不同的设备配置
Android 应用需要适应许多不断变化的条件:窗口大小、区域设置、字体大小、深色和浅色主题等等。这些条件大多来源于用户控制的设备级值,并通过当前的 Configuration
实例公开。在测试中直接测试不同的配置很困难,因为测试必须配置设备级属性。
DeviceConfigurationOverride
是一个仅用于测试的 API,它允许您以本地化的方式为正在测试的 @Composable
内容模拟不同的设备配置。
DeviceConfigurationOverride
的伴生对象具有以下扩展函数,它们会覆盖设备级配置属性
DeviceConfigurationOverride.DarkMode()
:将系统覆盖为深色主题或浅色主题。DeviceConfigurationOverride.FontScale()
:覆盖系统字体比例。DeviceConfigurationOverride.FontWeightAdjustment()
:覆盖系统字体粗细调整。DeviceConfigurationOverride.ForcedSize()
:强制指定空间量,无论设备大小如何。DeviceConfigurationOverride.LayoutDirection()
:覆盖布局方向(从左到右或从右到左)。DeviceConfigurationOverride.Locales()
:覆盖区域设置。DeviceConfigurationOverride.RoundScreen()
:覆盖屏幕是否为圆形。
要应用特定的覆盖,请将正在测试的内容包装在对 DeviceConfigurationOverride()
顶级函数的调用中,并将要应用的覆盖作为参数传递。
例如,以下代码应用 DeviceConfigurationOverride.ForcedSize()
覆盖以本地更改密度,强制 MyScreen
可组合项在大横向窗口中渲染,即使运行测试的设备不直接支持该窗口大小
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
要同时应用多个覆盖,请使用 DeviceConfigurationOverride.then()
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
其他资源
- 在 Android 上测试应用:Android 测试主着陆页提供了更广泛的测试基础知识和技术视图。
- 测试基础知识:详细了解测试 Android 应用背后的核心概念。
- 本地测试:您可以在本地工作站上运行一些测试。
- 插桩测试:运行插桩测试也是一个好习惯。即直接在设备上运行的测试。
- 持续集成:持续集成允许您将测试集成到部署管道中。
- 测试不同屏幕尺寸:由于用户可用的设备众多,您应该测试不同的屏幕尺寸。
- Espresso:虽然专为基于视图的 UI 设计,但 Espresso 知识对于 Compose 测试的某些方面仍然有用。