Тесты Compose по умолчанию синхронизируются с вашим пользовательским интерфейсом. Когда вы вызываете утверждение или действие с помощью ComposeTestRule , тест синхронизируется заранее, ожидая, пока дерево пользовательского интерфейса не станет неактивным.
Обычно никаких действий предпринимать не нужно. Однако существуют некоторые исключения, о которых следует знать.
При синхронизации теста ваше приложение 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. В некоторых случаях вам может потребоваться остановить эту синхронизацию и управлять временем самостоятельно. Например, вы можете управлять временем, чтобы делать точные снимки экрана анимации в тот момент, когда пользовательский интерфейс еще занят. Чтобы отключить автоматическую синхронизацию, установите свойство 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 с другими частями теста или тестируемого приложения.
Функция 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 может быть полезно и для некоторых аспектов тестирования с помощью Compose.