常用模式

您可以使用完善的方法和模式测试您的Compose应用程序。

隔离测试

ComposeTestRule 允许您启动一个显示任何可组合项的活动:您的完整应用程序、单个屏幕或小型元素。检查您的可组合项是否正确封装并独立工作也是一个好习惯,这使得UI测试更容易、更集中。

这并不意味着您应该*只*创建单元UI测试。范围涵盖UI更大部分的UI测试也至关重要。

设置自己的内容后访问活动和资源

通常情况下,您需要使用composeTestRule.setContent设置被测内容,并且还需要访问活动资源,例如,断言显示的文本与字符串资源匹配。但是,如果您已经调用了setContent,则不能在使用createAndroidComposeRule()创建的规则上调用setContent

实现此目的的一种常见模式是使用空活动(例如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元素的状态是否正确恢复。使用StateRestorationTester类执行此类检查,而无需依赖于活动重新创建。

此类允许您模拟可组合项的重新创建。它对于验证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()顶级函数的调用中,并将要应用的覆盖作为参数传递。

例如,以下代码应用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测试的某些方面仍然很有帮助。