Тестирование — один из процессов, который может быть автоматизирован в рамках CI/CD. Надёжное и тщательное автоматизированное тестирование позволяет быть уверенным в новых сборках, снижает затраты на производство и повышает качество продукта. Но даже в крупных компаниях на больших проектах оно есть не всегда.
Обычно в тестирование начинают вкладываться, когда багов становится слишком много, недовольство клиентов растёт, и начинают «гореть» деньги бизнеса. Вместе с Александром Довнаром, Lead DevOps в Naviteq, мы разобрали, что такое непрерывное тестирование и какую роль оно занимает в CI/CD. А ещё рассмотрели кейс, как компании приходят к его внедрению, и что это внедрение даёт.
Непрерывная интеграция (CI) и тестирование
Практически все подходы к разработке программного обеспечения итерационные. Это значит, что команды двигаются 2-3-недельными спринтами, с каждым спринтом добавляя в продукт новые возможности. Работа над разными задачами ведётся параллельно, а кодовые базы разработчиков могут пересекаться. Чтобы это не приводило к багам и поломкам, внедряется CI-процесс.
Основная задача CI — сделать так, чтобы по мере параллельной работы над одной или разными кодовыми базами в конечном счёте получилась версия приложения, которую можно доставить в окружение. Для этого каждый кусок кода должен быть версионирован, протестирован и упакован в подходящий формат.
Если разработчик работает в локальной ветке и никак не затрагивает остальных членов команды, достаточно базовых проверок, что его код адекватен. Если же разработчик создаёт запрос на слияние с основной веткой и может потенциально затронуть своих коллег или конечных клиентов, необходима более сложная модель тестирования. В этом случае важно проверить, насколько корректно изменённый компонент работает с остальными компонентами. Для этого запускают unit-тесты, интеграционные тесты и тесты безопасности, позволяющие убедиться в отсутствии базовых нарушений.
Непрерывная доставка (CD) и тестирование
Есть два варианта расшифровки аббревиатуры CD — continuous delivery и continuous deployment.
Continuous delivery или непрерывная доставка — процесс, по окончании которого мы можем нажать на кнопку и доставить новую версию приложения нашим клиентам.
В continuous deployment или непрерывном развёртывании кнопки и ручного шага у нас нет. Всё проходит автоматически. Но поскольку выкатывать изменения клиентам в фоне без нашего участия сложно, непрерывное развёртывание возможно только при наличии стратегии тестирования и системы мониторинга. Тогда если вдруг что-то пойдёт не так, мы узнаем об этом раньше клиентов.
Из чего состоит CD: после CI у нас есть работающая версия приложения, мы разворачиваем в её разных окружениях и запускаем набор тестов. Обычно таких окружений три (но всё зависит от вашей схемы работы с системой контроля версий GIT и релизного процесса):
В dev окружение (окружение разработки) мы выкатываем все новые версии, в которых уже закончена разработка — это ещё не релизы, а просто новый функционал. Здесь мы проводим, как минимум, интеграционное тестирование и smoke-тестирование, чтобы убедиться, что наше приложение не сломалось.
Далее ветка, где велись изменения, сливается с основной веткой. И версию приложения, получившуюся после этого слияния, мы разворачиваем в staging окружении. На этом этапе мы запускаем E2E-тестирование (end-to-end тесты для проверки полного функционала), плюс, дополнительно обычно работает мануальный тестировщик, который будет проверять наше приложение как реальный пользователь. Также могут проводиться разнообразные security-тесты.
По завершении тестов мы говорим, что версия приложения стабильна, не имеет багов и готова к развёртыванию в продуктовой среде. Дальше всё зависит от того, какой процесс релизов установлен в команде. Мы либо разворачиваем всё вручную по кнопке, либо это происходит автоматически по наступлению какого-то события. В конце мы запускаем ряд тестов и просим проверить функционал наших тестировщиков и (или) реальных пользователей (например, если они готовы быть Beta-тестировщиками, и у нас есть Feature toggling в приложении). Далее следим за количеством ошибок в системах мониторинга и логах наших приложений, чтобы отловить потенциальные проблемы.
Окружений может быть больше, например, если мы собираемся проводить performance- и расширенные security-тесты. Запускать их на одном из трёх перечисленных окружений, значит потерять его на время, поэтому для них выделяют отдельные окружения.
Непрерывное тестирование (CT)
Непрерывное тестирование — то, что работает в пределах CI/CD вообще. Прежде чем организовать непрерывное тестирование как процесс, нам нужно сформировать стратегию тестирования: выделить группы тестов, которые мы будем запускать в разное время, чтобы проверить, насколько корректно работает приложение.
В CI-фазе важно, чтобы сборка проходила быстро, поэтому чаще всего применяют облегчённые типы тестов:
unit-тесты — чтобы протестировать отдельные компоненты;
интеграционные тесты — чтобы проверить интеграцию этих компонентов;
базовый линтинг — чтобы проверить код на соответствие тому, как мы договорились писать его внутри команды;
статистический код-анализ — чтобы отловить потенциальные уязвимости в нашем коде;
smoke-тесты — чтобы проверить, развернулось ли приложение, и корректно ли работают его базовые компоненты.
Можно делать больше тестов, но обычно этих 5 при условии, что они хорошо написаны, достаточно. Запустив их, мы уже предупредим около 90% багов на стадии CI.
На стадии CD идёт непрерывное тестирование конкретных окружений, поэтому тестов становится больше, и они дольше по времени:
E2E-тесты — чтобы проверить корректность работы UI;
performance-тесты — чтобы проверить, нет ли просадок по производительности;
регрессионные тесты — чтобы убедиться, что мы не вернулись к багам, исправленным в прошлом, перед выходом релиза на продакшн-среды;
security-тесты, «ломающие» наше приложение — чтобы проверить, что у нас нет уязвимостей;
penetration-тесты — чтобы проверить устойчивость приложения к взломам и отражению DDoS атак.
Глубина и набор тестов варьируются от окружения к окружению. Например, E2E-тестирование мы запускаем перед выходом в продакшн, когда хотим убедиться, что всё корректно работает. Если у нас не только веб-приложение, но ещё и версии для iOS и Android, такое тестирование может занять до двух дней в автоматическом режиме.
Разработка стратегии тестирования — работа не только опытных тестировщиков, но и DevOps-инженеров. Тесты являются частью CI/CD, поэтому специалисты, реализующие DevOps, тоже должны участвовать в их создании. Ещё не обойтись без представителей бизнеса, которые должны дать на всё это деньги. Разработка непрерывного тестирования — это долго и дорого, но в долгосрочной перспективе она даёт невероятные результаты.
Как понять, что пора проводить тестирования
Представим стартап в вакууме, который создаётся двумя программистами. Первый пишет фронтенд, второй — бэкенд, и из всего, что связано с DevOps, у них есть только Git. Свой единственный продакшн они используют, чтобы показывать потенциальным инвесторам продукт, а любые изменения тестируют локально.
Постепенно они находят инвестиции, и их MVP начинает обрастать расширенным функционалом. Заниматься разработкой вдвоём становится сложно, они нанимают 4 фронтенд-разработчика и 6 бэкенд-разработчиков. Команда из 10 разработчиков может работать параллельно над разным функционалом, поэтому на этой стадии развития логично внедрить контейнеризацию и CI. Тогда локальные стенды, на которых тестируется функционал, будут отражать реальную ситуацию в конечных окружениях.
Стартап развивается дальше, удаётся получить первых клиентов. Но клиенты готовы оплачивать подписку, только если, условно, будут получать новый функционал каждый месяц. Разработчики говорят, что раз в месяц, будут релизить новый функционал, но обещания клиентам не всегда совпадают с возможностями — горят дедлайны, появляются ошибки и т.д.
Дальше есть два пути развития:
либо очень много работать и постоянно исправлять стихийно появляющиеся баги, чтобы не потерять клиентов;
либо выделить по одному разработчику из команд фронтенда и бэкенда, чтобы они начали покрывать тестами существующую кодовую базу. А ещё договориться внутри, что теперь весь новый функционал будет покрываться хотя бы unit-тестами.
Второй вариант позволяет защитить себя от самоошибок, которые часто появляются при разработке, и способствует развитию — команда понимает пользу unit-тестов и постепенно внедряет интеграционное тестирование, улучшает стабильность и качество релизов.
Стартап продолжает масштабироваться, штат растёт, появляются новые команды. Помимо веб-версии, продукт обзаводится версиями для iOS и Android, и тестов требуется больше. Разработчики не любят тестировать код, и тогда им на помощь приходят инженеры, специализирующиеся на таких задачах, — тестировщики. Они начинают отлавливать ошибки вручную и внедрять автоматизированные тесты.
Конечно, это идеальная картина в вакууме, которой не всегда удаётся достичь в жизни. Но когда проект активно масштабируется, без такого подхода сложно держать высокое качество продукта. И непрерывное тестирование при правильной стратегии как раз позволяет выйти на уровень, когда ты перестаёшь бояться выкатывать новые релизы.
Коротко о главном: зачем нужно непрерывное тестирование
Команды, использующие непрерывное тестирование, могут добиться следующих результатов:
Быстрые и стабильные релизы. Благодаря непрерывным циклам обратной связи, вы рано находите баги и оперативно исправляете их. Время на разработку и выпуск релиза сокращается.
Высокая эффективность. За счёт автоматизации ресурсы команды расходуются более рационально. Разработчики могут сосредоточиться на разработке, а тестировщики — отказаться от повторяющихся задач в пользу задач, требующих критического и творческого мышления. В результате охват и качество тестов могут быть увеличены.
Снижение рисков. Автоматизация позволяет исключить человеческий фактор. Роботы выполняют повторяющиеся задачи с большим количеством данных лучше и быстрее людей. Риски в области автоматического тестирования снижаются.
Уменьшение затрат. Автоматизация тестирования позволяет раньше обнаруживать баги и ошибки. А чем раньше они обнаружены, тем проще и дешевле их исправить.
Для тех, кто хочет научиться работать с CI/CD и автоматизировать тестирование
20 июня в Слёрм стартует усовершенствованный курс «CI/CD на примере Gitlab CI». Вы пройдёте путь от создания самого простого пайплайна до настройки сложных вариантов CI/CD с возможностью отката на предыдущую версию.
Посмотреть программу и записаться: https://slurm.club/3NvNhSb