Всем привет!
Автотесты под Android — это непросто. Чтобы выстроить процесс автотестирования, надо запланировать и решить множество задач. Но самая большая беда заключается в том, что нигде нет полного описания, что вообще включает в себя автотестирование под Android, каковы его основные стадии. Отсутствует цельная картина. Этой статьей мы хотим восполнить пробел.
Она также выступит в роли схематичной дорожной карты работы Avokado Project. Мы верим в то, что в скором времени разворачивание автотестирования будет занимать куда меньше времени, чем сейчас. И активно работаем в этом направлении.
Зачем нужны автотесты?
Есть мнение, что UI-тесты не нужны, если у вас достаточное количество юнит- и интеграционных тестов. Но от следующей метафоры никуда не деться. Представьте, что вы собираете велосипед. У вас есть два хорошо протестированных колеса, протестированная рама вместе с седлом, протестированная система педалей с цепью и рулем. То есть мы с вами имеем хороший набор интеграционных и юнит-тестов. А велосипед-то в итоге поедет? Чтобы это проверить, вы нанимаете ручных тестировщиков, которые перед каждым релизом должны убедиться, что безупречные детали корректно взаимодействуют друг с другом, и велосипед будет ездить и доставлять пользователю удовольствие.
Так же и с любым программным обеспечением для мобилок. К сожалению, в мобильном мире мы не можем откатить неудачные изменения быстро, ведь все обновления идут через Google Play Store и App Store, что сразу накладывает ограничения в виде долгой раскатки в сравнении с веб- и backend-аналогами, обязательной совместимости версий и зависимости от решения пользователя обновляться или нет. Поэтому нам критически важно всегда убеждаться перед релизом, что основные пользовательские сценарии приложения работают именно так, как ожидается.
При этом, когда релизный цикл у вас длиной в несколько месяцев, вполне достаточно работы ручных тестировщиков и некоторого покрытия кода юнит- и интеграционными тестами. Однако во времена, когда релизный цикл стремительно сокращается до одной-двух недель (а то и еще меньше), сил ручных тестировщиков зачастую уже не хватает, что вынуждает или жертвовать качеством проверки, или нанимать больше специалистов.
Все это естественным образом подводит к необходимости автоматизации проверки пользовательских сценариев, то есть написания end-to-end- или автотестов. У «Авито» есть рассказ о том, как автотесты помогают и сколько они стоят (2019 год). Однако большинство команд такой метод отпугивает своей сложностью и необходимостью вкладывать существенные ресурсы, чтобы выстроить процесс. Это возвращает нас к цели данной статьи и вообще к одной из целей Avokado Project — стандартизировать процесс автотестирования в Android и существенно уменьшить его стоимость.
Картина целиком
Итак, обещанная картина целиком.
Если вы чего-то не понимаете, не переживайте. Мы сейчас пройдемся подробно по всем пунктам.
Процесс написания тестов
На первом шаге давайте попробуем написать тесты у себя на машине и запустить их локально.
Выбор инструментов для написания автотестов
Стоит сразу определиться со стеком технологий, который мы будем использовать для написания тестов.
Первая развилка — это выбор между кроссплатформенным решением (Appium и т. д.) и нативным решением (Espresso, UI Automator). Много копий сломано в этих спорах. Рекомендуем посмотреть выступление наших коллег, полное драматизма и накала страстей.
Спойлер — мы за нативные решения. По нашему опыту, они:
- стабильнее;
- быстрее;
- лучше интегрированы в IDE;
- не содержат слоев, которые вносят нестабильность и заставляют иметь суперширокие экспертные знания.
Кроме того, Google поддерживает Espresso и UI Automator.
Больше почитать про сравнение вы можете в статьях:
- Appium vs Espresso: Key Differences.
- Appium vs. Espresso: Which Framework to Use for Automated Android Testing.
- Appium vs Espresso: The Most Popular Automation Testing Framework in 2019.
На чистом Espresso и UIAutomator нынче редко кто пишет. Разработчики сделали различные удобные обертки, которые решают их проблемы. Сейчас у нас готовится статья об этих инструментах с классификацией и сравнением. Если кратко, то фреймворк, на который мы делаем ставку, это Kaspresso.
Kaspresso
Kaspresso — это фреймворк, который:
- предоставляет DSL, значительно облегчающий написание автотестов;
- дает встроенную многоуровневую защиту от флекающих тестов;
- ускоряет работу UI Automator;
- предоставляет полные логи о том, что происходит в тесте;
- дает возможность запуска любых ADB-команд внутри тестов;
- предоставляет механизм интерцепторов для перехвата всех действий и проверок. На данном механизме построено логирование и защита от нестабильных тестов;
- описывает лучшие практики (исходя из нашего опыта) по написанию автотестов.
Вы можете прочитать о Kaspresso на GitHub и Habr.
Test runner
Вы написали несколько тестов. Теперь их нужно запустить. За этот этап отвечает Test Runner, или просто раннер.
Что нам предлагает Google? Утилиту AndroidJUnitRunner и ее специальный режим — Orchestrator. AndroidJUnitRunner делает то, что от него и требуется — просто запускает тесты, позволяя еще и параллелить их выполнение. Orchestrator позволяет продолжить выполнение тестов, даже если некоторые из них упали, и дает возможность минимизировать общее состояние между тестами. Так достигается изоляция исполнения каждого теста.
Но со временем требований к раннеру становится все больше. Вот некоторые из них:
- запускать отдельные группы тестов;
- запускать тесты только на определенных девайсах;
- перезапускать упавшие тесты (вторая волна защиты от последствий нестабильных тестов после Kaspresso);
- эффективно распределять тесты по девайсам с учетом истории прогонов и успешности предыдущих запусков;
- подготавливать отчеты о прогоне в разных форматах;
- отображать результаты прогона (желательно Allure based);
- поддержать истории прогонов для дальнейшего анализа;
- просто интегрироваться с вашей инфраструктурой.
На рынке есть несколько сторонних раннеров. Среди всех них, самым перспективным мы считаем Marathon, который довольно быстро настраивается и удовлетворяет части обозначенных выше требований. Например, он поддерживает распараллеливание тестов и подготовку результатов прогона в формате, пригодном для отображения в Allure.
Однако, Marаthon, к сожалению, не обладает некоторыми важными, по нашему мнению, свойствами. В частности, в нем нет:
- Простой и нативной интеграции раннера с инфраструктурой, которая выдает эмуляторы. А еще лучше возможности сразу же запустить ваши тесты в облаке. Впрочем, это проблема не только Marathon — к сожалению, ни один известный нам раннер не берет на себя ответственность за получение эмуляторов, это всегда ложится на плечи разработчиков.
- Плотной интеграции с фреймворками типа Kaspresso для получения максимальной, точной и корректной информации о тесте.
Кроме того, мы считаем, что раннер должен быть платформенным, то есть либо для Android, либо для iOS. Это обусловлено уникальной спецификой каждой ОС и вытекающей отсюда сложностью внесения изменений в раннер.
Поэтому прямо сейчас мы работаем над Avito Runner, в котором хотим собрать все лучшие и зарекомендовавшие себя наработки и идеи. Ждите будущих анонсов!
На чем запускать тесты
Параллельно с вопросом о том, какой раннер выбрать для тестов, перед вами встает другой: а на чем лучше запускать тесты? Есть три опции:
- Настоящий девайс.
Плюсы. Покажет проблемы, специфичные для конкретных устройств и прошивок. Многие производители меняют Android под себя — как UI, так и логику работы ОС. И бывает полезно проверить, что ваше приложение корректно работает в таком окружении.
Минусы. Необходимо где-то добыть ферму устройств, организовать специальное помещение под них — необходима низкая температура, нежелательно попадание прямых солнечных лучей и т. д. Кроме того, аккумуляторы имеют свойство вздуваться и выходить из строя. А еще сами тесты могут менять состояние устройства, и вы не можете просто взять и откатиться на какой-то стабильный снепшот. - Чистый эмулятор.
Под «чистым» мы подразумеваем, что вы запускаете эмулятор у себя или где-то на машине, используя установленный на эту машину AVD Manager.
Плюсы. Быстрее, удобнее и стабильнее настоящего устройства. Создание нового эмулятора занимает считаные минуты. Никаких проблем с отдельным помещением, аккумуляторами и прочим.
Минусы. Отсутствие упомянутых выше device specifics. Однако зачастую количество тестовых сценариев, завязанных на специфику устройства, ничтожно мало, и они не высокоприоритетные. Но самый главный минус — это плохая масштабируемость. Простая задача залить новую версию эмулятора на все хосты превращается в мучение. - Docker-образ Android-эмулятора.
Docker решает недостатки чистых эмуляторов.
Плюсы. Docker и соответствующая обвязка в виде подготовки и раскатки образа эмулятора — это полноценное масштабируемое решение, позволяющее быстро и качественно готовить эмуляторы и раскатывать их на все хосты, обеспечивая их достаточную изолированность.
Минусы. Более высокий входной порог.
Мы делаем ставку на Docker.
В сети есть разные Docker-образы Android-эмуляторов, мы рекомендуем обратить внимание на следующие:
Как уже было упомянуто выше, подготовка образа требует некоторой сноровки. Плюс зачастую есть желание эмулятор преднастроить: выключить анимацию, залогиниться в аккаунт Google, выключить Google Play Protect и многое другое. Все эти вещи непросто организовать. Поэтому в скором времени мы хотим выкатить подробную документацию о том, как готовить и использовать образы быстро.
Инфраструктура
Вы написали сотни UI-тестов. Часть из них вы хотите запускать в рамках PR, а значит, весь тестовый набор должен проходить в максимально короткие сроки, например, до 20 минут. Вот тут наступает настоящее масштабирование.
Однако эта область — темный лес для части Android-разработчиков и автоматизаторов. Оно и немудрено, ведь инфраструктура требует знаний железа, конфигурирования серверов, DevOps-практик и прочего. Поэтому обязательно наладьте контакты с людьми, которые во всем этом разбираются, у себя в компании или вовне, ведь они сильно помогут и уберегут вас от ошибок.
Итак, что вам примерно предстоит:
- Выбор между облачным решением, локальным решением с нуля и локальным решением на базе чего-то, если в компании есть своя инфраструктура по запуску тестов других платформ.
- Самое трудоемкое — это развертывание внутренней инфраструктуры с нуля. В этом случае необходимо подобрать железо, которое будет максимально использоваться автотестами. Придется измерять нагрузку на CPU/GPU/Memory/Disk, а еще пробовать разное количество одновременно запущенных эмуляторов и смотреть за стабильностью тестов. Это большая тема, по которой мы хотим провести современные замеры и поделиться с вами своими рекомендациями.
Дальнейшая накатка необходимого ПО, встраивание в сети и прочее — это все за DevOps-инженерами. - На выходе должен быть какой-то сервис, единая точка, которая отдает вам эмуляторы. Это может быть Kubernetes, может быть облачный сервис типа Google Cloud Engine или какое-то кастомное решение.
В его настройке опять-таки помогают DevOps-инженеры. - Связка полученного сервиса с Test Runner.
Одна из задач Avito Runner — сделать такую связку максимально простой и прозрачной, а также предоставить точки расширения, которые помогут вам легко внедрить свой кастомный сервис.
В ближайшее время мы планируем выпустить Avito Runner и статьи, которые помогут настроить инфраструктуру.
Остальное
Не забывайте про такие немаловажные моменты, как:
- вывод отчета по прогону тестов (Allure);
- внедрение/синхронизация с TMS;
- интеграция в CI/CD;
- обучение разработчиков и тестировщиков;
- процессы — кто, когда, сколько и какие автотесты пишет.
Про все это мы еще обязательно поговорим.
Заключение
Мы постарались описать основные части становления автотестирования под Android. Надеемся, что теперь у вас в головах сложится тот самый пазл, который позволит видеть картину целиком.
Следите за анонсами на нашем сайте и в телеграм-канале.