Проверьте активность вашего приложения

Активности служат контейнерами для всех взаимодействий пользователя внутри вашего приложения, поэтому важно протестировать, как активности вашего приложения ведут себя во время событий на уровне устройства, таких как следующие:

  • Другое приложение, например, телефонное приложение устройства, прерывает работу вашего приложения.
  • Система уничтожает и воссоздает вашу активность.
  • Пользователь переводит вашу активность в новую оконную среду, например, в режим «картинка в картинке» (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()
            }
        }
    }
}

Дополнительные ресурсы

Для получения дополнительной информации о тестировании см. следующие дополнительные ресурсы:

Документация