🔥 Важное для QA-специалистов! 🔥
В QaRocks ты найдешь туториалы, задачи и полезные книги, которых нет в открытом доступе. Уже более 15.000 подписчиков – будь среди нас! Заходи к нам в телеграм канал QaRocks
Перевод статьи «How Dropbox leverages testing to maintain high level of trust at scale».
В этой статье Райан Хартер, ведущий инженер Dropbox, рассказывает про тестирование и изменения в пирамиде тестирования. Также он рассуждает о том, какие инструменты помогают команде получать своевременную обратную связь и укреплять доверие пользователей.
Содержание
- С чего все начиналось
- Как это сейчас
- Модульное тестирование
- Сквозное тестирование
- Скриншот-тестирование
- Ручное тестирование
- Дальнейшие планы
Приложение Dropbox для Android насчитывает более миллиарда загрузок. И, конечно же, оно должно поддерживать высокую планку качества – как для самих пользователей, так и для разных сценариев использования. Android-инженеров в команде меньше 30, а для полной уверенности в коде одного ручного тестирования недостаточно. И чтобы постоянно удовлетворять потребности пользователей, мы пробуем разные подходы в тестировании.
В Dropbox пользователь может легко открыть свои файлы с любого устройства. Поэтому Android-приложение должно поддерживать просмотр максимального количества типов файлов (медиа, документы, фото и любые их сочетания). А таким функциям, как Camera Uploads (автоматический бэкап всех важных фотографий), нужна глубокая интеграция с Android, которая существенно менялась во времени и отличается по версиям систем. И всё это должно работать без ошибок, чтобы пользователям не приходилось ни о чем волноваться… ведь кому из нас хочется переживать о возможной потере данных?
За прошедшие годы в Android-команде Dropbox многое изменилось. Тем не менее, на первом месте у нас так и осталось одно: постоянно создавать и улучшать функции приложения, сохраняя тот уровень доверия со стороны пользователей, которым славится компания. Я бы хотел рассказать, как Dropbox удается поддерживать доверие пользователей на примере изменений в наших подходах к тестированию.
С чего все начиналось
Автоматизированное тестирование всегда было важной частью инженерной культуры в Dropbox, но выполнять его на Android не так-то просто. Много лет назад Dropbox инвестировал в инфраструктуру с акцентом на сквозное тестирование. Присмотревшись к инструментальным тестам на Android, мы разработали тестовые хелперы для проверки функционала приложения по шаблону ‘Robot Pattern’. Так мы смогли создать большой набор тестов, которые имитировали перемещение пользователя внутри приложения. Но этот подход требовал серьезных вложений.
Сначала Dropbox, как и большинство Android-приложений того времени, был монолитным модулем. В долгосрочной перспективе такое решение весьма нерационально. Поэтому мы декомпозировали монолит в более модульную архитектуру. Но набор сквозных тестов не был в приоритете из-за сложных зависимостей. В результате он так и остался монолитным. Тестовый код не присутствовал рядом с кодом проверяемого функционала, поэтому о нем часто забывали. Постепенно он устаревал.
Не стоит забывать и о том, что для монолитных модулей со множеством зависимостей характерно длительное время сборки. Плюс тесты, которые выполнялись на эмуляторах нашей CI-среды. Все это замедляло циклы обратной связи для сквозного тестирования. В результате инженеры предпочитали удалить непройденный тест, а не обновить его.
Затем экосистема Android начала все больше присматриваться к автоматизированному тестированию. Появились полезные библиотеки (Espresso, Robolectric), а еще добавилась поддержка модульного тестирования, встроенная непосредственно в Gradle. Dropbox шел в ногу со временем, отказавшись от повального использования сквозных тестов в пользу модульных и заполнив ими нижний уровень ранее перевернутой пирамиды тестирования. Это был знаменательный шаг для тестового покрытия в приложении. Теперь мы могли внедрять такие QA-практики, как базовое покрытие кода, и гарантировать постоянное повышение надежности продукта по мере его развития.
Со временем модульное тестирование упрощалось, а инженеры все больше разочаровывались в медленных циклах обратной связи сквозных тестов. И тогда наша пирамида тестирования перекосилась в другую сторону. Мы были уверены в своих модульных тестах и поддерживающей их инфраструктуре. Но наши сквозные тесты устаревали без поддержки, становясь все более и более ненадежными. Дошло до того, что мы практически не обращали внимания на их сбои. Тесты, которым нельзя доверять, теряют свою значимость и ложатся тяжким бременем на обслуживание. Вот тогда мы поняли: нужно что-то менять.
Как это сейчас
За последний год мы удвоили свой акцент на надежность. Мы инвестировали в тестовую инфраструктуру, дав инженерам не только возможность, но и стимул писать качественные, ценные тесты на всех уровнях пирамиды тестирования. Помимо технических инвестиций в код и инструментарий, мы уделили время оценке тестирования (что мы тестируем, как мы это делаем). Кроме того, поработали над тем, чтобы вся команда лучше понимала, каким инструментом пользоваться и когда.
Модульное тестирование
Большая часть нашей работы по-прежнему состоит в написании модульных тестов. Это быстрые и целенаправленные тесты. Они дают нам своевременную обратную связь и служат первой линией защиты от регрессий. По возможности мы пишем JUnit-тесты, а при необходимости возвращаемся к инструментальным тестам. Благодаря совместимости Robolectric с AndroidX Test, мы смогли перенести многие инструментальные тесты в модульные на виртуалке Java. Это еще больше облегчило достижение наших целей по тестовому покрытию.
К слову о целях тестового покрытия. Уровень модульного тестирования – это единственный слой, в котором мы определяем покрытие кода. По умолчанию стремимся к охвату в 80%. Хотя у нас также есть процесс, позволяющий переписать эту цель, если модульные тесты невыполнимы или нецелесообразны.
Примечание. Несмотря на то, что мы оцениваем тестовое покрытие через стандартный инструментарий JaCoCo, в нем отсутствует глубокое понимание Kotlin. И это создает нам определенные проблемы. Например, пока что мы не нашли способа сообщить JaCoCo, что сгенерированным методам доступа toString и hashCode в «не поведенческих» классах данных не нужно тестовое покрытие. Мы экспериментируем и изучаем альтернативы, чтобы не писать хрупкие, бесполезные тесты, но пока что по-прежнему вынуждены переопределять покрытие.
Сквозное тестирование
В последние месяцы мы стали больше инвестировать в автоматизированный набор сквозных тестов. Этот набор предупреждает нас о критически важных проблемах, которые не в состоянии найти модульные тесты. Например, проблемы в интеграции с ОС или неожиданные ответы API. Мы тщательно улучшали инфраструктуру, чтобы инженерам было проще запускать тесты локально. Кроме того, провели аудит, удалив некачественные и некорректные тесты. А еще проработали документацию и обучение, поддерживая наших инженеров в работе с наборами сквозных тестов.
Как я уже говорил, наши сквозные тесты имитируют перемещение пользователя в самом приложении. Таким образом, задача по определению данных тест-кейсов – это не просто инженерная проблема. Поэтому мы разработали руководства, которые помогают нашим инженерам вместе с партнерами по продукту и дизайну определять тест-кейсы с реальными сценариями использования.
Не так давно мы ввели практику использования правильных критериев готовности в задачах разработки. Это чек-лист того, что нужно сделать, чтобы проект считался «готовым». Пункты из чек-листа определяются и согласуются в начале работы над проектом. В наш типовой чек-лист включается описание сквозных тест-кейсов по проекту. Так мы показываем, что добавляем тест-кейсы продуманно, с учетом их ценности и назначения, а не гонимся за произвольными цифрами покрытия.
Скриншот-тестирование
За последние годы мы развили еще одно направление тестов – скриншот-тестирование. Через него мы проверяем визуальные регрессии, а также следим за правильным отображением в светлых и темных темах, при разной ориентации и форм-факторах.
Если говорить о модульных тестах, то для скриншот-тестирования мы используем Paparazzi. С ним у нас получается писать быстрые и изолированные тесты. А еще мы пришли к выводу, что эта библиотека хороша для тестирования отдельного представления или композиционных макетов, включая компоненты нашей дизайн-системы.
Кроме того, для нас полезно запускать скриншот-тесты в полнофункциональных инструментальных тестах. Для этих целей мы пользуемся собственной библиотекой Dropshots. Она поддерживает скриншот-тестирование на устройствах и эмуляторах. Через скриншоты на реальных (или эмулированных) устройствах мы можем проверить такие системные интеграции, как отображение edge-to-edge (от края до края) и режим окна по умолчанию на устройствах Android 15.
Ручное тестирование
Учитывая все наши инвестиции в автоматизированное тестирование, можно подумать, что мы совсем не занимаемся ручным тестированием. Но даже сейчас это попросту невозможно. Есть много процессов, для которых автотесты слишком сложны в написании или проверке. Например, проверка корректного поведения приложения при отображении содержимого файлов. В данном случае мы пользуемся и модульными, и сквозными тестами. Но бывает и так, что содержимое файла сложно проверить программными средствами, а скриншот-тесты оказываются хрупкими.
Тогда мы обращаемся к веб-инструменту для управления тест-кейсами и через него поддерживаем полный набор ручных тест-кейсов. Затем, перед каждым релизом, прогоняем тесты в стороннем сервисе тестирования. Так нам удается отлавливать проблемы, для которых еще не написали тесты, либо когда требуется человеческое суждение.
Дальнейшие планы
Тестирование оказывает неоценимую помощь в обнаружении проблем с качеством до того, как их заметят пользователи. Именно оно помогает нам заслужить доверие клиентов. Понимая всю важность тестирования, мы намерены и дальше инвестировать в эту область, поддерживая высокое качество и надежность своего продукта.
В настоящее время я занимаюсь расширением функционала Dropshots для поддержки нескольких конфигураций устройств. Это позволит нам выполнять скриншот-тесты на разных устройствах через один набор тестов. Приложение Dropbox работает на разных форм-факторах. Поэтому для нас важно одновременно запускать наборы скриншот-тестов на разных устройствах/эмуляторах и предотвращать регрессии на менее популярных форм-факторах.
Кроме того, мы начинаем экспериментировать со скриншот-тестами Compose Preview. Здесь функция Compose Preview выполняет двойную работу: ускоряет цикл разработки и одновременно защищает от регрессии.
Помимо прочего, мы намерены и дальше следить за балансом разных видов тестирования. Балансировка нашей пирамиды доказывает, что мы инвестируем в эту сферу ради надежности, а не в погоне за субъективными показателями покрытия. Мы уже убедились в ценности качественного набора тестов. И мы продолжим инвестировать в это направление, чтобы оставаться достойными доверия пользователей.
