Ресурсы эспрессо на холостом ходу

Ресурс в режиме ожидания представляет собой асинхронную операцию, результаты которой влияют на последующие операции в тесте пользовательского интерфейса. Зарегистрировав простаивающие ресурсы с помощью Espresso, вы можете более надежно проверять эти асинхронные операции при тестировании вашего приложения.

Определите, когда необходимы ресурсы на холостом ходу

Espresso предоставляет сложный набор возможностей синхронизации . Однако эта характеристика платформы применима только к операциям, которые отправляют сообщения в MessageQueue , например к подклассу View , который отображает свое содержимое на экране.

Поскольку Espresso не знает о каких-либо других асинхронных операциях, включая те, которые выполняются в фоновом потоке, Espresso не может предоставить гарантии синхронизации в таких ситуациях. Чтобы сообщить Espresso о длительных операциях вашего приложения, вы должны зарегистрировать каждую из них как неактивный ресурс.

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

  • Добавление вызовов Thread.sleep() . Когда вы добавляете искусственные задержки в свои тесты, завершение выполнения вашего набора тестов занимает больше времени, и ваши тесты все равно могут иногда давать сбой при выполнении на более медленных устройствах. Кроме того, эти задержки плохо масштабируются, поскольку в будущем выпуске вашему приложению, возможно, придется выполнять более трудоемкую асинхронную работу.
  • Реализация оболочек повторных попыток, которые используют цикл для многократной проверки, выполняет ли ваше приложение асинхронную работу до тех пор, пока не наступит тайм-аут. Даже если вы укажете максимальное количество повторов в своих тестах, каждое повторное выполнение потребляет системные ресурсы, особенно процессор.
  • Использование экземпляров CountDownLatch , которые позволяют одному или нескольким потокам ожидать завершения определенного количества операций, выполняемых в другом потоке. Эти объекты требуют, чтобы вы указали длину тайм-аута; в противном случае ваше приложение может быть заблокировано на неопределенный срок. Защелки также усложняют ваш код, усложняя обслуживание.

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

Распространенные случаи использования

При выполнении в тестах операций, подобных приведенным ниже примерам, рассмотрите возможность использования ресурса на холостом ходу:

  • Загрузка данных из Интернета или локального источника данных.
  • Установление соединений с базами данных и обратные вызовы.
  • Управление службами с помощью системной службы или экземпляра IntentService .
  • Выполнение сложной бизнес-логики , например преобразований растровых изображений.

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

Пример реализации ресурсов на холостом ходу

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

CountingIdlingResource
Ведет счетчик активных задач. Когда счетчик равен нулю, связанный ресурс считается простаивающим. Эта функциональность очень похожа на функциональность Semaphore . В большинстве случаев этой реализации достаточно для управления асинхронной работой вашего приложения во время тестирования.
UriIdlingResource
Аналогично CountingIdlingResource , но счетчик должен быть равен нулю в течение определенного периода времени, прежде чем ресурс будет считаться бездействующим. Этот дополнительный период ожидания учитывает последовательные сетевые запросы, когда приложение в вашем потоке может сделать новый запрос сразу после получения ответа на предыдущий запрос.
IdlingThreadPoolExecutor
Пользовательская реализация ThreadPoolExecutor , которая отслеживает общее количество запущенных задач в созданных пулах потоков. Этот класс использует CountingIdlingResource для ведения счетчика активных задач.
IdlingScheduledThreadPoolExecutor
Пользовательская реализация ScheduledThreadPoolExecutor . Он предоставляет те же функциональные возможности и возможности, что и класс IdlingThreadPoolExecutor , но также может отслеживать задачи, запланированные на будущее или периодически выполняемые.

Создайте свой собственный ресурс холостого хода

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

Если вы реализуете собственную функциональность ресурсов бездействия, помните о следующих рекомендациях, особенно о первом:

Вызов переходов в состояние ожидания вне проверок простоя.
После того, как ваше приложение станет бездействующим, вызовите onTransitionToIdle() вне любых реализаций isIdleNow() . Таким образом, Espresso не выполняет вторую, ненужную проверку, чтобы определить, простаивает ли данный неактивный ресурс.

Следующий фрагмент кода иллюстрирует эту рекомендацию:

Котлин

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

Ява

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
Зарегистрируйте простаивающие ресурсы до того, как они вам понадобятся.

Преимущества синхронизации, связанные с бездействием ресурсов, вступают в силу только после первого вызова Espresso метода isIdleNow() этого ресурса.

В следующем списке показано несколько примеров этого свойства:

  • Если вы зарегистрируете ресурс простоя в методе, помеченном @Before , ресурс простоя вступит в силу в первой строке каждого теста.
  • Если вы зарегистрируете ресурс простоя внутри теста, ресурс простоя вступит в силу во время следующего действия на основе Espresso. Такое поведение по-прежнему происходит, даже если следующее действие находится в том же тесте, что и оператор, регистрирующий бездействующий ресурс.
Отмените регистрацию неиспользуемых ресурсов после того, как вы закончите их использовать.

Чтобы сохранить системные ресурсы, вам следует отменить регистрацию неиспользуемых ресурсов, как только они вам больше не нужны. Например, если вы регистрируете неактивный ресурс в методе, помеченном @Before , лучше всего отменить регистрацию этого ресурса в соответствующем методе, помеченном @After .

Используйте реестр простоя для регистрации и отмены регистрации ресурсов бездействия.

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

Поддерживайте только простое состояние приложения в пределах простаивающих ресурсов.

Например, ресурсы простоя, которые вы реализуете и регистрируете, не должны содержать ссылки на объекты View .

Регистрация простаивающих ресурсов

Espresso предоставляет класс-контейнер, в который вы можете поместить простаивающие ресурсы вашего приложения. Этот класс, называемый IdlingRegistry , представляет собой автономный артефакт, который вносит минимальные накладные расходы в ваше приложение. Класс также позволяет вам предпринять следующие шаги для улучшения удобства сопровождения вашего приложения:

  • Создайте ссылку на IdlingRegistry вместо содержащихся в нем ресурсов бездействия в тестах вашего приложения.
  • Сохраняйте различия в наборе неиспользуемых ресурсов, которые вы используете для каждого варианта сборки.
  • Определите ресурсы простоя в службах вашего приложения, а не в компонентах пользовательского интерфейса, которые ссылаются на эти службы.

Интегрируйте ресурсы простоя в свое приложение

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

При добавлении ресурсов простоя в ваше приложение мы настоятельно рекомендуем разместить логику ресурсов простоя в самом приложении и выполнять в тестах только операции регистрации и отмены регистрации.

Хотя при таком подходе вы создаете необычную ситуацию использования интерфейса только для тестирования в рабочем коде, вы можете обернуть простаивающие ресурсы вокруг уже имеющегося кода, сохраняя размер APK вашего приложения и количество методов.

Альтернативные подходы

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

  • Создавайте варианты сборки, такие как версии продукта Gradle, и используйте ресурсы простоя только в отладочной сборке вашего приложения.
  • Используйте платформу внедрения зависимостей, такую ​​​​как Dagger , чтобы внедрить график зависимости ресурсов вашего приложения в режиме ожидания в ваши тесты. Если вы используете Dagger 2, сама инъекция должна происходить из подкомпонента.
  • Реализуйте ресурс бездействия в тестах вашего приложения и откройте ту часть реализации вашего приложения, которую необходимо синхронизировать в этих тестах.

    Внимание: хотя это дизайнерское решение, похоже, создает автономную ссылку на простаивающие ресурсы, оно также нарушает инкапсуляцию во всех приложениях, кроме самых простых.

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

Для получения дополнительной информации об использовании Espresso в тестах Android обратитесь к следующим ресурсам.

Образцы