Инструкции

Альтернативы простаиванию ресурсов в тестах Compose: API waitUntil (обновлено)

3 минуты чтения
Jose Alcérreca
Инженер по связям с разработчиками

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

[Обновление 2023 года] Краткое содержание: используйте новые API waitUntil для синхронизации в тестах Compose (версия 1.4.0+).


Что такое синхронизация?

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

Нажмите Enter или щелкните, чтобы просмотреть изображение в полном размере.

large_0_9n_Nqkt_HHUTOQ_In_AI_b113b43bcf.png
Различные области тестирования в приложении

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

Нажмите Enter или щелкните, чтобы просмотреть изображение в полном размере.

large_correct_b1a355f41b.webp
Надлежащая синхронизация между тестовой версией и приложением.

androidx.test и, соответственно, Compose Test используются некоторые внутренние механизмы, позволяющие избежать лишних проблем. Например, если основной поток занят, тест приостанавливается до тех пор, пока не сможет выполнить следующую строку кода.

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

Вариант 1: простаивающие ресурсы

Функция «Простаивающие ресурсы» в Espresso позволяет разработчику решать, когда приложение занято. Использовать её можно двумя способами:

1. Установка их в фреймворк или библиотеку, выполняющую работу, которую тест не видит.

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

2. Внесение изменений в тестируемый код для явного отображения информации о том, занято ли ваше приложение или нет.

Например, вы можете изменить свой репозиторий (или тестовый двойник ), чтобы указать, что он занят во время загрузки данных из источника данных:

Это не идеально, потому что вы загрязняете свой производственный код или создаёте сложные тестовые дубликаты, и в некоторых ситуациях их сложно установить. Например, как бы вы использовали Idling Resources в Kotlin Flow? Какое обновление является последним ?

Вместо этого мы можем подождать .

Вариант 2: Ожидание… неправильным способом

Загрузка данных обычно происходит быстро, особенно при использовании фиктивных данных, так зачем тратить время на простаивающие ресурсы, если можно просто приостановить выполнение теста на пару секунд?

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

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

0_DOCdjq-JpPDGV5OB.png

Вариант 3: Дождаться, пока всё произойдёт как надо!

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

1_jIYFxE4qlHXMi2SwW6JemA.png

В Compose можно использовать функцию waitUntil , которая принимает другую функцию, возвращающую логическое значение.

Обновление от 22.03.2023: начиная с версии Compose 1.4.0, мы добавили новый набор API для waitUntil:

[До версии 1.4.0: Используйте следующие вспомогательные функции: waitUntilExists , waitUntilNodeCount ]

…и используйте их следующим образом:

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

Когда же его следует использовать? Хороший пример — загрузка данных из Observable (с помощью LiveData, Kotlin Flow или RxJava). Когда вашему пользовательскому интерфейсу необходимо получить несколько обновлений, прежде чем вы сочтете его неактивным, вы можете упростить синхронизацию, используя waitUntil .

Например, когда вы получаете поток данных из представления:

И вы отправляете в него несколько элементов:

Если repository возвращает первый результат неопределенное время, тестовая среда будет считать, что состояние «Загрузка» — это состояние простоя (начальное значение, присвоенное в collectAsState ), и продолжит выполнение следующего оператора.

Таким образом, вы можете значительно повысить надежность теста, если убедитесь, что в пользовательском интерфейсе не отображается индикатор загрузки:


Удачных… подождите… испытаний!


Лицензия на фрагменты кода:

Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0
Автор:

Продолжить чтение