В этой теме у меня мало опыта, вероятность белиберды увеличена втрое.
Сейчас компетентность в сфере TestOps является таким же базовым требованием к QA-инженерам, как и написание автоматизированных тестов. Причина - в активном развитии CI/CD в проектах и необходимости QA-инженерам работать с пайплайнами
Многие начинающие автоматизаторы бросаются учить язык программирования, пишут первые учебные тесты и даже успешно делают тестовые задания по автоматизации тест-кейсов. Однако не все задумываются о том, что с этими тестами в реальной работе делать дальше. Кто их будет запускать? Когда? Каким образом? Здесь я бы хотел рассказать о пайплайне CI, месте автотестов в нем, а так же как и на чем тесты запускаются.
Прежде всего, откуда этот пайплайн взялся и что за CI/CD.
Непрерывная интеграция (Continuous Integration, CI) и непрерывная поставка (Continuous Delivery, CD) представляют собой культуру, набор принципов и практик, которые позволяют разработчикам чаще и надежнее развертывать изменения программного обеспечения.
CI/CD - это одна из DevOps-практик. Она также относится и к agile-практикам: автоматизация развертывания позволяет разработчикам сосредоточиться на реализации бизнес-требований, на качестве кода и безопасности.
Непрерывная интеграция (Continuous Integration, CI) - это практика разработки программного обеспечения, которая заключается в автоматическом и регулярном объединении (интеграции) кода, написанного разными членами команды разработчиков, в общий репозиторий или хранилище кода. Основная цель непрерывной интеграции - обеспечить раннюю обнаружение и устранение конфликтов, ошибок и проблем интеграции в процессе разработки.
Основные элементы и практики непрерывной интеграции включают:
-
Автоматическую сборку (Build Automation): Автоматическое создание исполняемых файлов (бинарных файлов) из исходного кода после каждого коммита в репозиторий.
-
Автоматическое тестирование (Automated Testing): Запуск автоматических тестов, включая модульные, интеграционные и функциональные тесты, для проверки работоспособности приложения после интеграции нового кода.
-
Интеграцию сборок и тестов (Integration of Builds and Tests): Интеграция сборки и тестирования в автоматический процесс CI.
-
Обнаружение конфликтов (Conflict Detection): Раннее обнаружение конфликтов между коммитами разных разработчиков, которые могут вызвать ошибки интеграции.
-
Автоматическое развертывание (Automated Deployment): Автоматическое развертывание собранного и протестированного приложения на тестовых или staging-серверах.
-
Мониторинг результатов (Monitoring of Results): Отслеживание результатов сборок и тестов с целью быстрого реагирования на ошибки.
-
Автоматическое уведомление (Automated Notification): Автоматическое уведомление команды разработчиков о результатах сборки и тестирования.
-
Восстановление после сбоев (Failure Recovery): Восстановление процесса CI после сбоев и автоматическое уведомление о сбоях.
-
Использование инструментов CI/CD (CI/CD Tools): Использование специализированных инструментов и платформ для реализации процессов непрерывной интеграции и доставки (Continuous Delivery, CD).
Целью непрерывной интеграции является ускорение процесса разработки, повышение качества кода и уменьшение рисков, связанных с интеграцией и слиянием кода. CI также способствует автоматизации процессов и улучшению сотрудничества между членами команды разработки.
Непрерывная поставка (Continuous Delivery, CD) - это практика разработки программного обеспечения, которая расширяет принцип непрерывной интеграции (CI) и включает в себя автоматическое развертывание (доставку) приложения в целевую среду (production, staging, testing и т. д.) после успешного завершения процесса непрерывной интеграции и тестирования. Основная цель непрерывной поставки - обеспечить готовность к выпуску новых версий приложения в любой момент времени.
Основные элементы и практики непрерывной поставки включают:
-
Автоматическое развертывание (Automated Deployment): Автоматическое развертывание приложения на целевых серверах или платформах после успешного прохождения тестов в процессе CI.
-
Автоматический пайплайн (Automated Pipeline): Создание автоматизированного пайплайна (цепи поставок), который включает в себя этапы сборки, тестирования и развертывания.
-
Управление конфигурацией (Configuration Management): Управление конфигурациями целевых сред и ресурсов для обеспечения консистентности и воспроизводимости развертывания.
-
Управление версиями (Version Control): Использование систем управления версиями для контроля изменений в коде, конфигурации и ресурсах приложения.
-
Автоматическое уведомление (Automated Notification): Автоматическое уведомление команды разработки и операций о статусе процесса поставки.
-
Мониторинг и обратная связь (Monitoring and Feedback): Установление мониторинга производительности и доступности приложения в реальном времени, а также получение обратной связи для быстрого реагирования на сбои и проблемы.
-
Резервное копирование и восстановление (Backup and Recovery): Разработка процедур резервного копирования данных и возможности восстановления при необходимости.
-
Разделение на этапы (Staging): Использование этапа предварительного развертывания (staging) для проверки приложения перед финальным развертыванием в продакшн.
-
Оперативное развертывание (Rolling Deployment): Внедрение новой версии приложения путем поэтапного переключения пользователей на новую версию без простоев и перерывов в работе.
-
Микросервисная архитектура (Microservices): Использование архитектуры, основанной на микросервисах, для более гибкой и быстрой поставки.
Целью непрерывной поставки является создание процесса разработки, который позволяет командам доставлять новые версии приложения в любой момент времени с минимальными рисками и максимальной автоматизацией. Это позволяет организациям быстро реагировать на изменения в требованиях клиентов и рынка, улучшать качество и стабильность продукта и увеличивать эффективность разработки.
Инструменты CI/CD помогают настраивать специфические параметры окружения, которые конфигурируются при развертывании. А также CI/CD-автоматизация выполняет необходимые запросы к веб-серверам, базам данных и другим сервисам, которые могут нуждаться в перезапуске или выполнении каких-то дополнительных действий при развертывании приложения.
Непрерывная интеграция и непрерывная поставка нуждаются в непрерывном тестировании, поскольку конечная цель - разработка качественных приложений. Непрерывное тестирование часто реализуется в виде набора различных автоматизированных тестов (регрессионных, производительности и других), которые выполняются в CI/CD-конвейере (pipeline, build chain и т.д.). Зрелая практика CI/CD позволяет реализовать непрерывное развертывание: при успешном прохождении кода через CI/CD-конвейер, сборки автоматически развертываются в продакшн-окружении. Команды, практикующие непрерывную поставку, могут позволить себе ежедневное или даже ежечасное развертывание.
Типичный CD-конвейер состоит из этапов сборки, тестирования и развертывания. Более сложные конвейеры включают в себя следующие этапы:
- Получение кода из системы контроля версий и выполнение сборки;
- Настройка инфраструктуры, автоматизированной через подход “инфраструктура как код”;
- Копирование кода в целевую среду;
- Настройка переменных окружения для целевой среды;
- Развертывание компонентов приложения (веб-серверы, API-сервисы, базы данных);
- Выполнение дополнительных действий, таких как перезапуск сервисов или вызов сервисов, необходимых для работоспособности новых изменений;
- Выполнение тестов и откат изменений окружения в случае провала тестов;
- Логирование и отправка оповещений о состоянии поставки.
Например, в Jenkins конвейер определяется в файле Jenkinsfile, в котором описываются различные этапы, такие как сборка (build), тестирование (test) и развертывание (deploy). Там же описываются переменные окружения, секретные ключи, сертификаты и другие параметры, которые можно использовать в этапах конвейера. В разделе post настраивается обработка ошибок и уведомления. В более сложном CD-конвейере могут быть дополнительные этапы, такие как синхронизация данных, архивирование информационных ресурсов, установка обновлений и патчей. CI/CD-инструменты обычно поддерживают плагины. Например, у Jenkins есть более 1500 плагинов для интеграции со сторонними платформами, для расширения пользовательского интерфейса, администрирования, управления исходным кодом и сборкой.
Многие команды, использующие CI/CD-конвейеры в облаках используют контейнеры, такие как Docker, и системы оркестрации, такие как Kubernetes. Контейнеры позволяют стандартизировать упаковку, поставку и упростить масштабирование и уничтожение окружений с непостоянной нагрузкой. Есть множество вариантов совместного использования контейнеров, инфраструктуры как код (Iaas) и CI/CD-конвейеров. Архитектура бессерверных вычислений представляет собой еще один способ развертывания и масштабирования приложений. В бессерверном окружении инфраструктурой полностью управляет поставщик облачных услуг, а приложение потребляет ресурсы по мере необходимости в соответствии с его настройками. Например, в AWS бессерверные приложения запускаются через функции AWS Lambda, развертывание которых может быть интегрировано в CI/CD-конвейер Jenkins с помощью плагина.
Больше о CI/CD можно почитать тут и тут.
Этапы конвейера
В момент, когда триггерится сборка, например, когда разработчик сделал коммит в свою ветку, запускается процесс, который выполняется специально написанными скриптами и утилитами. Этот процесс состоит из нескольких обязательных шагов. Простой пример для PR:
- При открытии каждого Pull Request, Git-сервер отправляет уведомление CI-серверу;
- CI-сервер клонирует репозиторий, проверяет исходную ветку (например bugfix/wrong-sorting), и сливает код с кодом master-ветке;
- Тогда запускается билд-скрипт (сценарий сборки). Например ./gradlew build;
- Если эта команда возвращает код ответа “0”, то билд успешно выполнен. (Другой ответ означает ошибку);
- CI-сервер направляет уведомление об успешном билде на Git-сервер;
- Если билд был успешен, то Pull Request разрешается слить с существующим кодом. (Если не успешен, то, соответственно, не разрешается).
Ошибка в любом из шагов приводит к полному падению всей сборки. Ну и, само собой разумеется, шаги расположены в таком порядке, чтобы сужать воронку потенциальных проблем. Если Quality Gate предыдущего этапа не пройдет, то на проверку следующего уже можно не тратить ресурсы.
Пример Quality Gates, которые встроены в pipeline отсюда:
- Сборка сервиса:
- Проверка наличия конфигурации корректного формата;
- Проверка стандартов оформления кода;
- Проверка на необходимое покрытие Unit-тестами;
- Генерации и публикации контрактов (контроль обратной совместимости).
- Запуск Beta-тестов;
- Обязательный code-review;
- Сканирование на уязвимости.
Пример сферического пайплайна в вакууме отсюда:
- Code scanning: код проверяется на соответствие общему гайдлайну (linters), уязвимости (code security) и качество (code quality);
- Unit tests;
- Build: этап для сборки artifacts/packages/images и т.д. Здесь уже можно задуматься о том, каким будет стратегия версионирования всего приложения. Во времена контейнеризации, в первую очередь интересуют образы для контейнеров и способы их версионирования;
- Scan package: пакет/образ собрали. Теперь нужно просканировать его на уязвимости. Современные registry уже содержат инструментарий для этого;
- Deploy: стадия для развертывания приложения в различных окружениях;
- Integration testing: приложение задеплоили. Оно где-то живет в отдельном контуре. Наступает этап интеграционного тестирования. Тестирование может быть как ручным, так и автоматизированным;
- Performance testing (load/stress testing): данный вид тестирования имеет смысл проводить на stage/pre-production окружениях. С тем условием, что ресурсные мощности на нем такие же, как в production;
- Code Review / Approved: одним из важнейших этапов являются Merge Request. Именно в них могут производиться отдельные действия в pipeline перед слиянием, а также назначаться группы лиц, требующих одобрения перед слиянием.
Больше про build-agent можно почитать тут: TeamCity: настраиваем CI/CD в вашей команде и тут Что такое сборщик продукта, про окружения тут Создаем инфраструктуру для интеграционных тестов
Е2Е автотесты
Теперь пора поговорить непосредственно про то, что чаще всего касается рядового автоматизатора - Е2Е автотесты. Как мы выяснили выше, до прогона Е2Е сборка сначала проходит несколько шагов, а условиями запуска чаще являются ключевые моменты: commit, pull request и merge request. В моей прошлой компании был очень простой конвейер, где на коммит в фича-ветку запускались тесты разработчика, на вливание в develop стартовали критичные Е2Е тесты, а на вливание в main уже всё что есть, включая регрессионные тесты. Теперь, когда известны места автотестов в конвейере, нужно еще понять, на чем эти тесты будут прогоняться и как имея скрипт автотеста его запустить в конвейере.
Все эти моменты конфигурируются в самом CI-агенте, в jenkins это были джобы (job). Пример: How to Add your First Android Job to Jenkins. За запуск кода тестов, когда вы инициируете запуск из конвейера или локально, отвечает Test Runner. Это лишь одна из задач, в зону ответственности раннера входят:
- подготовка окружения;
- формирование набора тестов для исполнения;
- запуск тестов;
- получение результатов выполнения тестов;
- подготовка отчетов о прохождении тестов;
- сбор статистики.
Несмотря на то, что с фреймворком поставляется также и раннер, существует возможность использования более совершенных сторонних раннеров.
Параллельно с вопросом о том, какой раннер выбрать для тестов, перед вами встает другой: а на чем лучше запускать тесты? Есть три опции:
- Настоящий девайс.
- Плюсы. Покажет проблемы, специфичные для конкретных устройств и прошивок. Многие производители меняют Android под себя - как UI, так и логику работы ОС. И бывает полезно проверить, что ваше приложение корректно работает в таком окружении.
- Минусы. Необходимо где-то добыть ферму устройств, организовать специальное помещение под них - необходима низкая температура, нежелательно попадание прямых солнечных лучей и т. д. Кроме того, аккумуляторы имеют свойство вздуваться и выходить из строя. А еще сами тесты могут менять состояние устройства, и вы не можете просто взять и откатиться на какой-то стабильный снепшот.
- Чистый эмулятор. Под «чистым» мы подразумеваем, что вы запускаете эмулятор у себя или где-то на машине, используя установленный на эту машину AVD Manager.
- Плюсы. Быстрее, удобнее и стабильнее настоящего устройства. Создание нового эмулятора занимает считаные минуты. Никаких проблем с отдельным помещением, аккумуляторами и прочим.
- Минусы. Отсутствие упомянутых выше device specifics. Однако зачастую количество тестовых сценариев, завязанных на специфику устройства, ничтожно мало, и они не высокоприоритетные. Но самый главный минус - это плохая масштабируемость. Простая задача залить новую версию эмулятора на все хосты превращается в мучение.
- Docker-образ Android-эмулятора. Docker решает недостатки чистых эмуляторов.
- Плюсы. Docker и соответствующая обвязка в виде подготовки и раскатки образа эмулятора - это полноценное масштабируемое решение, позволяющее быстро и качественно готовить эмуляторы и раскатывать их на все хосты, обеспечивая их достаточную изолированность.
- Минусы. Более высокий входной порог.
В сети есть разные Docker-образы Android-эмуляторов:
Предстоит сделать сложный выбор между облачным решением, локальным решением с нуля и локальным решением на базе чего-то, если в компании есть своя инфраструктура по запуску тестов других платформ. Вся эта инфраструктура уже связывается с раннером для запуска тестов, после чего уже решаются остальные моменты, такие как вывод отчета по прогону тестов (например, Allure) и внедрение/синхронизация с TMS.
Источники:
- Что такое CI/CD? Разбираемся с непрерывной интеграцией и непрерывной поставкой
- Разбираемся в CI/CD
- Автотесты на Android. Картина целиком
Доп. материал:
- Continuous Testing в CI/CD: что это, зачем нужно и как работает
- DevOps инструменты не только для DevOps. Процесс построения инфраструктуры автоматизации тестирования с нуля
- Руководство для начинающих: создаем DevOps-пайплайн
- Зачем CI/CD тестировщикам?
- Jenkins Pipeline. Что это и как использовать в тестировании
- ГДЕ И КАК ПРОГОНЯТЬ UI ТЕСТЫ
- Инфраструктура + тестирование = любовь
- Leadership in test: a guide to infrastructure and environments
- Leadership in test: testing tools
- Создаем инфраструктуру для интеграционных тестов
- HOW TO RUN API SMOKE TESTS IN YOUR CONTINUOUS DEPLOYMENT PIPELINE
- Разбираемся в CI/CD
- Что такое CI (Continuous Integration)
- Как мы настроили CI/CD, чтобы релизить часто и без страха
- Как настроить Pipeline для Jenkins, Selenoid, Allure
- CI-билд - это не елка
- Идеальный пайплайн в вакууме
- Основные подходы к CI/CD для целей тестирования ПО
- How To Have Seamless Script Execution Planning And Reporting For Success Of An Automation Project
- Что такое сборщик продукта
- #8 QA инфраструктура компании на локальной машине. Docker, Jenkins, Jira, Selenoid, Allure.
- Автотесты и Docker
- Интеграция с Allure: структурировать, упростить, стабилизировать
- Автоматизация расчета покрытия требований и его визуализация в Allure Report
- Что такое Docker
- Continuous Integration with Jenkins
- Стратегии деплоя в Kubernetes: rolling, recreate, blue/green, canary, dark (A/B-тестирование)
- Как e2e автотесты на Selenide помогают QA-команде при частых релизах
- Как ускорить автотесты
- Тестируем CI Pipeline
- Switchboard: набор инструментов для управления авто-тестами
- Централизованное логирование в Docker с применением ELK Stack
- Строим домашний CI/CD при помощи GitHub Actions и Python
- Нагрузочное тестирование как CI-сервис для разработчиков
- Автоматическое тестирование микросервисов в Docker для непрерывной интеграции
- Тесты на pytest с генерацией отчетов в Allure с использованием Docker и Gitlab Pages и частично selenium
- Автоматизация системных тестов на базе QEMU (Часть 1/2)
- Как сократить время сборки образов Docker в GitLab CI
- Crash-crash, baby. Автоматический мониторинг фатальных ошибок мобильных приложений
- Anna: готовим отчет о тестировании API, чтобы все были довольны
- git-flow, GitHub flow, GitLab Flow