Вы можете протестировать свое приложение Compose, используя хорошо зарекомендовавшие себя подходы и шаблоны.
Тестирование в изоляции
ComposeTestRule позволяет запустить активность, отображающую любой компонуемый объект: всё приложение целиком, отдельный экран или небольшой элемент. Также рекомендуется проверять, правильно ли инкапсулированы ваши компонуемые объекты и работают ли они независимо друг от друга, что упрощает и делает более целенаправленным тестирование пользовательского интерфейса.
Это не значит, что нужно создавать только модульные UI-тесты. UI-тесты, охватывающие более крупные части вашего пользовательского интерфейса, также очень важны.
После настройки собственного контента получите доступ к активности и ресурсам.
Зачастую вам необходимо установить проверяемое содержимое с помощью метода composeTestRule.setContent , а также получить доступ к ресурсам активности, например, чтобы проверить, соответствует ли отображаемый текст строковому ресурсу. Однако вы не можете вызвать setContent для правила, созданного с помощью createAndroidComposeRule() , если активность уже вызывает этот метод.
Распространенный способ достижения этой цели — создание AndroidComposeTestRule с использованием пустой активности, например ComponentActivity .
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.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 : Хотя этот язык программирования предназначен для пользовательских интерфейсов на основе представлений, знание Espresso может быть полезно и для некоторых аспектов тестирования с помощью Compose.