Как начать работу с непрерывной интеграцией

Узнайте, как внедрить непрерывную интеграцию и автоматизированное тестирование за пять шагов.

Sten Pittet Sten Pittet

Непрерывная интеграция (CI) — это рекомендация Agile и DevOps, с учетом которой разработчики интегрируют код в основную ветку или репозиторий кода как можно раньше и достаточно часто. Цель состоит в том, чтобы избежать стресса при интеграции, который случается, когда все разработчики ожидают окончания проекта или спринта, чтобы выполнить слияние своих частей работы. Непрерывная интеграция автоматизирует развертывание, а также помогает командам выполнять бизнес-требования, улучшать качество кода и повышать безопасность.

Одним из основных преимуществ внедрения CI является то, что этот подход экономит ваше время в течение всего цикла разработки благодаря раннему выявлению и устранению конфликтов. Кроме того, это отличный способ сократить время, затрачиваемое на устранение багов и ухудшений, путем создания качественного комплекта тестов. Наконец, это помогает всей команде лучше понимать базу кода и возможности, которые разрабатываются для клиентов.

Первый шаг на пути к непрерывной интеграции — настройка автоматического тестирования.

Начало работы с автоматическим тестированием

Понимание различий между видами тестов

Если вы хотите воспользоваться всеми преимуществами непрерывной интеграции, вам понадобится автоматизировать свои тесты, чтобы запускать их для каждого изменения, вносимого в основной репозиторий. Мы настоятельно рекомендуем запускать тесты на каждой ветке репозитория, а не только на основной. Это позволит своевременно выявлять проблемы и свести к минимуму сбои в работе вашей команды.

Существует много видов тестов, но если вы только приступаете к внедрению новшеств, нет необходимости делать все и сразу. Начните с малого: реализуйте модульные тесты и постепенно работайте над увеличением покрытия кода.

  • Модульные тесты работают в узких областях и обычно проверяют поведение отдельных методов или функций.
  • Интеграционные тесты проверяют, насколько правильно взаимодействуют несколько компонентов. Такие тесты могут задействовать несколько классов или выполнять тестирование интеграции с другими сервисами.
  • Приемочные тесты похожи на интеграционные тесты, но они ориентированы на бизнес-сценарии, а не на сами компоненты.
  • Тесты пользовательского интерфейса обеспечивают, что приложение корректно функционирует с точки зрения пользователя.

Не все тесты одинаковы. Пирамида тестов, разработанная Майком Коном, помогает визуализировать компромиссы, на которые приходится идти при использовании того или иного вида тестов.

Треугольник тестирования

Модульные тесты являются быстрыми и незатратными в смысле реализации, поскольку они чаще всего выполняют проверку небольших фрагментов кода. С другой стороны, тесты пользовательского интерфейса будут сложными в реализации и медленными при выполнении, так как они часто требуют запуска полной среды, а также множества сервисов для эмуляции поведения браузера или мобильного устройства. Поэтому может быть разумно ограничить количество сложных тестов пользовательского интерфейса и положиться на хорошее модульное тестирование базовых компонентов, чтобы сборка выполнялась быстро, а разработчики как можно скорее получали обратную связь.

Автоматическое выполнение тестов

Чтобы внедрить непрерывную интеграцию, нужно запускать тесты для каждого изменения, которое отправляется в основную ветку. Для этого понадобится сервис, который осуществлял бы мониторинг репозитория и отслеживал отправку нового кода в базу. Существует множество подобных решений, которые работают как локально, так и в облаке. При выборе сервера потребуется учесть следующие моменты.

  • Где размещен ваш код? Может ли сервис CI получить доступ к базе кода? Есть ли у вас особые ограничения на то, где может находиться код?
  • Какая ОС и какие ресурсы требуются для вашего приложения? Поддерживаете ли вы среду приложения? Можете ли вы установить нужные зависимости для сборки и тестирования своего ПО?
  • Сколько ресурсов требуется для ваших тестов? Некоторые облачные приложения накладывают ограничения на ресурсы, которые можно использовать. Если ваше ПО потребляет много ресурсов, не исключено, что лучше будет разместить CI‑сервер за собственным брандмауэром.
  • Сколько разработчиков в вашей команде? Когда ваша команда начнет практиковать CI, она будет каждый день отправлять в основной репозиторий большое количество изменений. Чтобы разработчики быстро получали обратную связь, потребуется сократить время ожидания в очереди для сборок, а значит, вам понадобится сервис или сервер, который обеспечит необходимый уровень параллельности.

Раньше, как правило, приходилось устанавливать отдельный сервер непрерывной интеграции, например Bamboo или Jenkins, но теперь можно найти облачные решения, которые внедряются гораздо проще. Например, если код размещен в Bitbucket Cloud, можно использовать в своем репозитории возможность Pipelines, чтобы запускать тесты при каждой отправке изменений без необходимости настраивать отдельный сервер или агенты сборки и без ограничений в вопросах параллельного запуска тестов.

image: node:4.6.0 pipelines:   default:     - step:         script:           - npm install           - npm test

Пример конфигурации для тестирования репозитория JavaScript с помощью Bitbucket Pipelines

Используйте покрытие кода для выявления кода, не охваченного тестами

После внедрения автоматического тестирования хорошо бы объединить его с инструментом, измеряющим покрытие тестами. Такой инструмент обеспечит вам представление о том, какая часть базы кода покрыта комплектом тестов.

Рекомендуется стремиться к покрытию более 80 %, но будьте осторожны: не путайте высокий процент покрытия с высоким качеством выполняемых тестов. Инструмент оценки покрытия кода поможет найти код, не охваченный тестами, но в конечном итоге результат будет зависеть от качества ваших тестов.

На начальном этапе не спешите добиваться стопроцентного покрытия базы кода. Лучше примените инструмент измерения покрытия тестами для поиска критически важных компонентов приложения, для которых еще не созданы тесты, и начните с этого.

Рефакторинг — прекрасная возможность для добавления тестов

Если вы планируете внести в приложение значительные изменения, необходимо начать с написания приемочных тестов для возможностей, которые могут быть затронуты этими изменениями. Это позволит сохранить уверенность в том, что после рефакторизации кода или добавления новых возможностей оригинальная схема работы приложения не изменится

Внедрение непрерывной интеграции

Автоматическое тестирование является основной частью непрерывной интеграции, однако использовать только его недостаточно. Возможно, вам придется поработать над культурой своей команды, чтобы договориться, что разработчики не будут работать над какой-нибудь возможностью по нескольку дней без слияния изменений с основной веткой. Не менее полезно будет привить команде культуру «зеленой сборки».

Обеспечьте раннюю и частую интеграцию

Независимо от того, применяете вы разработку с центральной веткой или функциональные ветки, важно, чтобы разработчики как можно скорее интегрировали свои изменения в основной репозиторий. Если код находится в ветке или на рабочем компьютере разработчика слишком долго, вы рискуете получить слишком много конфликтов, которые будут требовать внимания после выполнения слияния в главную ветку.

Благодаря ранней интеграции вы уменьшаете масштабы изменений, что облегчает понимание возможных конфликтов. Еще одно преимущество состоит в том, что упрощается обмен знаниями между разработчиками, поскольку им приходится иметь дело с небольшими удобоваримыми изменениями.

Если вам придется вносить какие-либо изменения, которые могут повлиять на существующую возможность ПО, можно воспользоваться флагами возможностей, чтобы отключить эти изменения в рабочей среде, пока работа не будет завершена.

Постоянно поддерживайте сборку в зеленом состоянии

Если разработчик сломает сборку главной ветки, исправление ошибок станет главным приоритетом. Чем больше изменений попадет в сборку, пока она сломана, тем труднее понять, что именно стало причиной проблемы. В результате вы рискуете создать еще больше ошибок.

Стоит потратить время на работу над комплектом тестов, чтобы убедиться, что он может быстро обнаруживать сбои и как можно скорее предоставлять обратную связь разработчику, который внес изменения. Можно разделить тесты так, чтобы быстрые тесты (например, модульные) выполнялись до длительных тестов. Если обнаружение сбоев с помощью комплекта тестов будет происходить долго, вы отнимете у разработчиков много времени, так как им придется менять контекст для возвращения к предыдущей работе и исправления.

Не забудьте настроить уведомления, чтобы гарантировать, что разработчики получат предупреждения о проблемах со сборкой. Можно шагнуть дальше и отображать состояние основных веток на дашбоарде для всеобщего просмотра.

Пишите тесты как часть историй

Наконец, необходимо убедиться, что для каждой разрабатываемой возможности имеются автоматические тесты. Может показаться, что так вы замедлите разработку, но на самом деле это значительно сокращает время, которое команда тратит на исправление ухудшений или багов, возникающих при каждой итерации. Вы также сможете с уверенностью вносить изменения в свою базу кода, поскольку ваш комплект тестов позволит быстро убедиться, что все ранее разработанные возможности работают должным образом.

Чтобы написать хорошие тесты, нужно убедиться, что разработчики привлечены к участию в определении пользовательских историй на достаточно раннем этапе. Это отличный способ добиться более глубокого общего понимания бизнес-требований и упростить взаимодействие с менеджерами по продукту. Приступить к написанию тестов можно даже до внедрения кода, который они будут проверять.

Пишите тесты при устранении багов

Как при работе с существующей базой кода, так и в самом начале разработки в релизах, несомненно, будут попадаться баги. После устранения багов не забывайте добавлять тесты, которые будут предотвращать их повторное появление.

CI позволит вашим инженерам по контролю качества быстро масштабировать работу

С внедрением CI и автоматизации меняется и роль инженеров по контролю качества. Им больше не нужно вручную тестировать основные возможности приложения, а значит, они могут выделять больше времени на создание инструментов для упрощения работы разработчиков, а также помогать им внедрять правильные стратегии тестирования.

Когда вы начнете внедрять непрерывную интеграцию, инженеры по контролю качества смогут сосредоточиться на разработке тестов с использованием более удобных инструментов и массивов данных, а также помочь разработчикам оптимизировать навыки написания хорошего кода. Глубокое тестирование, тем не менее, по-прежнему будет проводиться в сложных случаях, но эта работа должна отнимать меньше времени.

Непрерывная интеграция за пять шагов

Теперь у вас должно быть хорошее представление о концепциях непрерывной интеграции и мы можем свести все описанное к следующим пунктам.

  1. Начните писать тесты для критически важных частей своей базы кода.
  2. Воспользуйтесь сервисом CI для автоматического запуска этих тестов при каждой отправке изменений в основной репозиторий.
  3. Убедитесь, что ваша команда проводит интеграцию изменений ежедневно.
  4. Исправляйте сборку сразу после возникновения ошибок.
  5. Пишите тесты для каждой новой истории, которую реализуете.

Хотя задача может показаться простой, для эффективной работы потребуется активное участие всей команды. Сначала придется замедлить выпуск релизов и заручиться поддержкой владельцев продукта, чтобы они не торопили разработчиков с поставкой новых возможностей без разработки тестов.

Мы рекомендуем начать с простых тестов, чтобы привыкнуть к новому режиму работы, и только затем переходить к реализации более сложного комплекта тестов, так как им может быть трудно управлять.