Тесты 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 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 и предназначено для пользовательских интерфейсов на основе представлений, оно все равно может быть полезным для некоторых аспектов тестирования Compose.