Тесты Compose синхронизируются по умолчанию с вашим UI. Когда вы вызываете утверждение или действие с ComposeTestRule
, тест синхронизируется заранее, ожидая, пока дерево UI не станет бездействующим.
Обычно вам не нужно предпринимать никаких действий. Однако есть некоторые крайние случаи, о которых вам следует знать.
Когда тест синхронизирован, ваше приложение 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 UI. В некоторых случаях вы можете захотеть остановить эту синхронизацию и управлять часами самостоятельно. Например, вы можете управлять временем, чтобы делать точные снимки экрана анимации в точке, где UI все еще будет занят. Чтобы отключить автоматическую синхронизацию, установите свойство autoAdvance
в mainClock
в false
:
composeTestRule.mainClock.autoAdvance = false
Обычно вы затем сами продвигаете время. Вы можете продвигать его ровно на один кадр с помощью advanceTimeByFrame()
или на определенную длительность с помощью advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Неиспользуемые ресурсы
Compose может синхронизировать тесты и пользовательский интерфейс, так что каждое действие и утверждение выполняется в состоянии ожидания, ожидая или продвигая часы по мере необходимости. Однако некоторые асинхронные операции, результаты которых влияют на состояние пользовательского интерфейса, могут выполняться в фоновом режиме, пока тест не знает о них.
Создайте и зарегистрируйте эти ресурсы бездействия в вашем тесте, чтобы они учитывались при принятии решения о том, занято или бездействует тестируемое приложение. Вам не нужно предпринимать никаких действий, если только вам не нужно регистрировать дополнительные ресурсы бездействия, например, если вы запускаете фоновое задание, которое не синхронизировано с Espresso или Compose.
Этот API очень похож на Idling Resources Espresso, чтобы указать, является ли тестируемый субъект бездействующим или занятым. Используйте тестовое правило Compose для регистрации реализации IdlingResource
.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
Ручная синхронизация
В некоторых случаях вам придется синхронизировать Compose UI с другими частями вашего теста или тестируемого вами приложения.
Функция 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, оно все равно может быть полезно для некоторых аспектов тестирования Compose.