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

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

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