您可以使用成熟的方法和模式测试您的 Compose 应用程序。
隔离测试
ComposeTestRule
允许您启动一个显示任何可组合元素的 Activity:您的完整应用程序、单个屏幕或小型元素。 作为最佳实践,还应该检查您的可组合元素是否正确封装且独立工作,从而简化和聚焦 UI 测试。
但这并不意味着您应该只创建单元 UI 测试。 作用域更大 UI 部分的 UI 测试同样非常重要。
在设置您自己的内容后访问 Activity 和资源
通常,您需要使用 composeTestRule.setContent
设置测试中的内容,并且还需要访问 Activity 资源,例如,断言显示的文本与字符串资源匹配。 但是,如果您创建的 Activity 已经调用了 setContent
,则无法在使用 createAndroidComposeRule()
创建的规则上调用它。
一种常见的模式是使用空的 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()
验证状态恢复
验证 Activity 或进程重新创建时 Compose 元素的状态是否被正确恢复。 使用 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:虽然旨在用于基于 View 的 UI,但 Espresso 知识对于 Compose 测试的某些方面仍然很有帮助。