Действия служат контейнерами для каждого взаимодействия пользователя с вашим приложением, поэтому важно проверить, как действия вашего приложения ведут себя во время событий на уровне устройства, таких как следующие:
- Другое приложение, например приложение для телефона на устройстве, прерывает работу вашего приложения.
- Система уничтожает и воссоздает вашу деятельность.
- Пользователь помещает свои действия в новую оконную среду, например «картинка в картинке» (PIP) или многооконную среду.
В частности, важно убедиться, что ваша активность ведет себя правильно в ответ на события, описанные в разделе Жизненный цикл активности .
В этом руководстве описывается, как оценить способность вашего приложения поддерживать целостность данных и удобство работы с пользователем при переходе действий вашего приложения через различные состояния своего жизненного цикла.
Управляйте состоянием активности
Одним из ключевых аспектов тестирования действий вашего приложения является размещение действий вашего приложения в определенных состояниях. Чтобы определить эту «заданную» часть ваших тестов, используйте экземпляры ActivityScenario
, входящие в библиотеку тестов AndroidX . Используя этот класс, вы можете поместить свою деятельность в состояния, имитирующие события на уровне устройства.
ActivityScenario
— это кроссплатформенный API, который можно использовать как в локальных модульных тестах, так и в интеграционных тестах на устройстве. На реальном или виртуальном устройстве ActivityScenario
обеспечивает безопасность потоков, синхронизируя события между потоком инструментирования вашего теста и потоком, который выполняет тестируемое действие.
API особенно хорошо подходит для оценки поведения тестируемого действия при его уничтожении или создании. В этом разделе представлены наиболее распространенные варианты использования, связанные с этим API.
Создать занятие
Чтобы создать тестируемое действие, добавьте код, показанный в следующем фрагменте:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use {
}
}
}
После создания действия ActivityScenario
переводит его в состояние RESUMED
. Это состояние указывает на то, что ваша активность выполняется и видна пользователям. В этом состоянии вы можете свободно взаимодействовать с элементами View
вашей активности с помощью тестов пользовательского интерфейса Espresso .
Google рекомендует вам close
об активности после завершения теста. Это очищает связанные ресурсы и повышает стабильность ваших тестов. ActivityScenario
реализует Closeable
, поэтому вы можете применить расширение use
или try-with-resources
на языке программирования Java, чтобы действие закрывалось автоматически.
Альтернативно вы можете использовать ActivityScenarioRule
для автоматического вызова ActivityScenario.launch
перед каждым тестом и ActivityScenario.close
при демонтаже теста. В следующем примере показано, как определить правило и получить из него экземпляр сценария:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>()
@Test fun testEvent() {
val scenario = activityScenarioRule.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
, как показано в следующем фрагменте кода:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testResult() {
launchActivity<MyActivity>().use {
onView(withId(R.id.finish_button)).perform(click())
// Activity under test is now finished.
val resultCode = scenario.result.resultCode
val resultData = scenario.result.resultData
}
}
}
Триггерные действия в действии
Все методы в ActivityScenario
блокируют вызовы, поэтому API требует, чтобы вы запускали их в потоке инструментирования.
Чтобы инициировать действия в тестируемой активности, используйте средства сопоставления представлений Espresso для взаимодействия с элементами в вашем представлении:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use {
onView(withId(R.id.refresh)).perform(click())
}
}
}
Однако если вам нужно вызвать метод самого действия, вы можете сделать это безопасно, реализовав ActivityAction
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
activity.handleSwipeToRefresh()
}
}
}
}