Активности служат контейнерами для всех взаимодействий пользователя внутри вашего приложения, поэтому важно протестировать, как активности вашего приложения ведут себя во время событий на уровне устройства, таких как следующие:
- Другое приложение, например, телефонное приложение устройства, прерывает работу вашего приложения.
- Система уничтожает и воссоздает вашу активность.
- Пользователь переводит вашу активность в новую оконную среду, например, в режим «картинка в картинке» (PIP) или многооконный режим.
В частности, важно убедиться, что ваша активность корректно реагирует на события, описанные в разделе «Жизненный цикл активности» .
В этом руководстве описывается, как оценить способность вашего приложения поддерживать целостность данных и обеспечивать удобство использования по мере того, как действия приложения проходят через различные стадии своего жизненного цикла.
Тестирование действий в Compose
При тестировании приложения, созданного с помощью Jetpack Compose, обычно используется createAndroidComposeRule для запуска активности и взаимодействия с компонентами пользовательского интерфейса.
Однако тестирование событий на уровне устройства, таких как изменения конфигурации или перевод активности в фоновый режим или её завершение системой, требует непосредственного управления жизненным циклом активности. Для этого используется базовая структура ActivityScenario .
Правило теста Compose автоматически обрабатывает и управляет этим сценарием. На протяжении всего этого руководства вы увидите следующий шаблон, используемый для преодоления разрыва между современным тестированием пользовательского интерфейса и стандартным управлением жизненным циклом:
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
// ...
}
Управляйте состоянием активности.
Один из ключевых аспектов тестирования активности вашего приложения — это размещение активности в определенных состояниях. Для определения этой «заданной» части ваших тестов используйте экземпляры класса ActivityScenario , входящего в библиотеку AndroidX Test . С помощью этого класса вы можете размещать свою активность в состояниях, имитирующих события на уровне устройства.
ActivityScenario — это кроссплатформенный API, который можно использовать как в локальных модульных тестах, так и в интеграционных тестах на устройстве. На реальном или виртуальном устройстве ActivityScenario обеспечивает потокобезопасность, синхронизируя события между потоком инструментирования теста и потоком, выполняющим тестируемое действие.
Этот API особенно хорошо подходит для оценки поведения тестируемой активности при ее уничтожении или создании. В этом разделе представлены наиболее распространенные варианты использования этого API.
Создать действие
Для создания тестируемого действия добавьте код, показанный в следующем фрагменте:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use {
}
}
}
После создания активности ActivityScenario переводит её в состояние RESUMED . Это состояние указывает на то, что ваша активность запущена и видна пользователям. В этом состоянии вы можете свободно взаимодействовать с компонентами вашей активности, используя API тестирования Compose .
Google рекомендует вызывать метод close для активности после завершения теста. Это освобождает связанные ресурсы и повышает стабильность тестов. ActivityScenario реализует Closeable , поэтому вы можете использовать расширение use , чтобы активность закрывалась автоматически.
В качестве альтернативы вы можете использовать createAndroidComposeRule для автоматического запуска активности перед каждым тестом, обработки завершения работы и предоставления доступа как к методам тестирования пользовательского интерфейса Compose, так и к базовому ActivityScenario . В следующем примере показано, как определить правило и получить из него экземпляр сценария:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
}
}
Переведите деятельность в новое состояние.
Чтобы перевести активность в другое состояние, например, CREATED или STARTED , вызовите метод moveToState . Это действие имитирует ситуацию, когда ваша активность остановлена или приостановлена, соответственно, из-за прерывания другим приложением или системным действием.
Пример использования функции moveToState приведен в следующем фрагменте кода:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.moveToState(State.CREATED)
}
}
}
Определите текущее состояние активности.
Чтобы определить текущее состояние тестируемой активности, получите значение поля state в объекте ActivityScenario . Проверка состояния тестируемой активности особенно полезна, если она перенаправляет на другую активность или завершается сама собой, как показано в следующем фрагменте кода:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
startActivity(Intent(activity, MyOtherActivity::class.java))
}
val originalActivityState = scenario.state
}
}
}
Воспроизведите это действие.
Когда на устройстве заканчиваются ресурсы, система может уничтожить активность, и вашему приложению потребуется воссоздать эту активность, когда пользователь вернется в приложение. Для имитации таких условий вызовите метод recreate :
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.recreate()
}
}
}
Класс ActivityScenario поддерживает сохраненное состояние экземпляра активности и любые объекты, аннотированные с помощью @NonConfigurationInstance . Эти объекты загружаются в новый экземпляр тестируемой активности.
Получить результаты активности
Чтобы получить код результата или данные, связанные с завершенной активностью, получите значение поля result в объекте ActivityScenario . Используя createAndroidComposeRule , вы можете легко запустить действие пользовательского интерфейса, завершающее активность, как показано в следующем фрагменте кода:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testResult() {
composeTestRule.onNodeWithTag("finish_button").performClick()
val scenario = composeTestRule.activityRule.scenario
val resultCode = scenario.result.resultCode
val resultData = scenario.result.resultData
}
}
Запускать действия в рамках активности
Все методы внутри ActivityScenario являются блокирующими вызовами, поэтому API требует их выполнения в потоке мониторинга.
Для запуска действий в тестируемой активности используйте API тестирования Compose для взаимодействия с вашими компонентами:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
composeTestRule.onNodeWithText("Refresh").performClick()
}
}
Однако если вам необходимо вызвать метод непосредственно в самой активности, вы можете сделать это безопасно, используя onActivity :
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
activity.handleSwipeToRefresh()
}
}
}
}
Дополнительные ресурсы
Для получения дополнительной информации о тестировании см. следующие дополнительные ресурсы: