Когда я пришел в Dropbox почти два года назад, меня попросили помочь улучшить скриншот-тестирование, в результате чего появился Dropshots. Хотя к тому времени я уже поиграл с ранними версиями Paparazzi, многие из наших тестов слишком сильно зависели от полноценных Activities и Fragments, чтобы использовать JUnit-тесты на стороннем хосте.
Чем больше я работал с тестами скриншотов, тем лучше понимал их возможности и ограничения.
Что предлагают тесты скриншотов
Тестирование снимков экрана может быть очень полезным для проверки того, что элементы на экране отображаются так, как вы ожидаете. С их помощью можно обнаружить визуальные изменения, которые в противном случае могли бы остаться незамеченными.
Например, если вы работаете над компонентами системы проектирования, тесты скриншотов помогут вам проверить внешний вид компонентов и выявить, когда их внешний вид изменяется. Когда это происходит, можно просмотреть визуальную диффузию изменений, чтобы убедиться, что они изменяются так, как вы ожидаете.
Последнее предложение, на мой взгляд, часто упускается при использовании скриншот-тестов в приложениях.
Соблазн тестов по скриншотам
Скриншот-тесты имеют интересную особенность: мы описываем наши экраны в коде, поэтому хотим их тестировать, но тестирование пользовательских интерфейсов является сложной задачей.
Другие инструменты тестирования пользовательского интерфейса, такие как Espresso и Compose Sematics, могут показаться запутанными и сложными в управлении.
На помощь приходят инструменты скриншот-тестирования, такие как Paparazzi, которые предлагают UI-тестирование непосредственно в тестах JUnit, без использования устройства. Это может показаться чрезвычайно ценным в наших усилиях обеспечения покрытия UI-кода, но это связано с некоторыми скрытыми расходами.
Скриншот-тесты проверяют внешний вид
Когда вы пишете скриншот-тест, вы проверяете не поведение программы, а ее внешний вид. Хотя иногда эти понятия объединяют, это не одно и то же.
Поскольку скриншот-тесты могут легко охватывать большие участки UI-кода, они позволяют легко увеличить покрытие кода, но важно помнить о том, что они действительно проверяют.
Например, если я тестирую экран условий предоставления услуг, я могу легко увеличить покрытие кода тестами просто добавив один скриншот-тест для проверки экрана.
Отлично! Мое хорошо протестированное приложение теперь защищено от регрессий!
Скриншот-тесты требуют ручной проверки
Перенесемся на пару месяцев вперед и представим, что вашим UX-дизайнерам не нравится, что условия предоставления услуг требуют двух нажатий. Они хотят обновить текст, предложив автоматически принимать условия предоставления услуг при регистрации. Вы послушно убираете этот надоедливый флажок, а тесты скриншотов успешно фиксируют, что внешний вид изменился, и показывают вот такую разницу.
Заметив, что единственным изменением на экране является удаление флажка, как и ожидалось, вы просто записываете новые скриншоты и продолжаете свой день.
После внедрения этого изменения в продакшен количество подписчиков резко сократится, поскольку без возможности установить флажок для включения кнопки отправки у пользователей просто не будет возможности продолжить работу.
Эти скриншот-тесты провалились. Хотя они, как и ожидалось, сообщили, что внешний вид экрана изменился, это само по себе не стало серьезным сигналом тревоги. Тесты предоставили информацию, которую автор и рецензент должны были интерпретировать, чтобы убедиться, что поведение такое же, как ожидалось. Это уже ручное тестирование.
Используйте правильные тесты
Несмотря на то, что скриншот-тесты, безусловно, ценны, мы должны быть уверены в том, что понимаем цену их использования. Они являются отличным способом защиты от визуальных регрессий и гарантируют, что наши компоненты пользовательского интерфейса выглядят так, как мы ожидаем, но они не являются прямой заменой более традиционным тестовым утверждениям.
Приведенный пример можно было бы протестировать с помощью семантических тестов с использованием правила ComposeTestRule, как это подробно описано в руководстве по тестированию компоновки, либо в виде инструментальных тестов, либо в виде тестов Robolectric.
Хотя эти тесты также могли быть проигнорированы или неправильно поняты, они обычно дают более тонкое понимание желаемого поведения, поскольку не зависят от визуальной интерпретации желаемого результата. Кроме того, такие тесты менее хрупкие, поскольку их не нужно обновлять при изменении шрифтов, цветов и других не связанных с ними вещей.
Заключение
В конечном счете, важно понимать, какие существуют различные инструменты тестирования, и использовать тот, который подходит для конкретной задачи. Скриншот-тесты отлично подходят для определения визуальных изменений, но при этом приходится вручную проверять эти изменения. Для тестирования поведения кода существуют более эффективные и надежные варианты.