Технологический консалтинг и разработка ПО
144,35
рейтинг
9 февраля в 19:25

Разработка → Ежедневные релизы — это не так уж страшно



Меня зовут Оксана Харчук, я работаю QA-инженером в DataArt чуть больше года. Расскажу, как в нашем проекте организован процесс работы, и как быть, если релиз каждый день.

Сначала, когда я только пришла в DataArt, слово «релиз» ассоциировалось у меня с чем-то страшным. Но, как оказалось, если процесс работы построен правильно, релизы даже каждый день — совсем не страшно, а очень даже удобно.Чтобы этого достичь, процесс разработки в нашем проекте построен на принципах непрерывной поставки (continuous delivery) и непрерывной интеграции (continuous integration).

Что такое Continuous delivery и Сontinuous integration?


Continuous delivery или непрерывная поставка ПО — набор практик и принципов, нацеленных на сборку, тестирование и поставку ПО быстрее и чаще. Непрерывная поставка качественного кода опирается, в свою очередь, на непрерывную интеграцию.

Сontinuous integration, или непрерывная интеграция — это практика разработки ПО, которая заключается в выполнении частых автоматизированных сборок проекта для скорейшего выявления и решения интеграционных проблем. Ведь ясно: если над разными частями кода работают несколько программистов, при интеграции этих частей возникает много трудностей. Непрерывная интеграция помогает справиться с ними.

Как работает непрерывная интеграция?



Разработчики выкачивают исходный код из репозитория, делают какие-либо изменения, а затем отправляют свои изменения обратно в репозиторий. После чего автоматически проходит сборка проекта, прогоняются тесты и отсылается отчет, что в измененном коде всё хорошо, и он сохранен.

А здесь детально показано, что происходит на этапе тестирования после сохранения измененного кода:



Первое, что прогоняется, — jar-файлы, затем параллельно:
  • war-файлы;
  • внешние сервисы,
  • интеграционные тесты;
  • JS-тесты;
  • статический анализ кода;
  • тесты с базой данных.

Затем друг за другом выполняются следующие действия: валидационная сборка, инсталляция сборки, развертывание на тестовом окружении и, наконец, Selenium-тесты.

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

Вот так построен процесс непрерывной поставки. Стоит еще сказать, что практику непрерывной поставки (continuous delivery) не нужно путать с практикой непрерывного развертывания (continuous deployment). Разница в том, что при непрерывной поставке на определенном этапе присутствует ручное тестирование, а непрерывное развертывание выполняется полностью автоматически:



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

Гибкая методология разработки



В проекте мы используем гибкую методологию разработки — Agile. Гибкая методология предполагает разработку ПО циклами. Каждый цикл представляет собой уменьшенный вариант IТ-проекта: анализ требований, планирование, разработка, сборка, тестирование, развертывание. По окончанию итерации заказчик получает готовую версию IТ-системы, и, если требуется, — дальнейшие приоритеты проекта пересматриваются. Затем цикл разработки запускается снова. В итоге создается решение, которое соответствует требованиям заказчика.



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

Однако тут возникает следующий вопрос: если код хранится в репозитории постоянно и если у нас непрерывная интеграция, как скрыть код, который будет реализовать новый еще не готовый функционал? Это делается с помощью конфигурационного флага, при помощи которого разработчики скрывают код, который отвечает за неготовый функционал (хотя, конечно, бывают и такие изменения, которые невозможно скрыть под конфигурационным флагом).

Процесс разработки нового функционала:

Итак, как мы разрабатываем новый функционал? Сначала получаем требования, после чего QA-команда, проанализировав и выяснив требования, начинает писать тест-кейсы. В это же время идет процесс разработки. После того как разработчики, дав добро на тестирование, включают конфигурационный флаг на тестовом окружении, QA-инженеры начинается функциональное тестирование. Пока QA-инженеры тестируют и находят ошибки, которые разработчики исправляют, автоматизаторы или Selenium-команда (так мы их называем), начинают процесс автоматизации тест-кейсов. После функционально тестирования проводится регрессионное тестирование.



Процесс релиза


Если всё хорошо, принимается решение, что новый функционал пойдет в продакшн. Как это делается? Все очень просто: разработчик коммитит включение конфигурационного флага, под которым был скрыт новый функционал. После коммита происходит развертывание новой версии продукта на тестовом окружении с уже доступным новым функционалом. Разработчик делает включение конфигурационного флага непосредственно перед днем, когда назначен релиз, чтобы изменение вошло в новую версию приложения, ту, которая будет выпускаться на продакшн.

Итак, после того, как флаг включен, и наш функционал доступен на тестовом окружении, прогоняются приемочные тесты. Процесс прогона приемочных тестов повторяется каждую ночь, вне зависимости от того, релизим мы новый функционал или исправленные баги. Набор тестов за ночь прогоняется дважды, чтобы минимизировать случайные падения. Эти приемочные тесты покрывают все высокоприоритетные случаи. Когда QA-команда приходит утром, то просматривает отчеты о ночном тестировании, и бывает так, что всё прошло не гладко: 1 – 2 % тестов упали или были не пройдены. Дабы убедиться, что это были всего лишь случайные падения или, наоборот, что автоматизированые тест-кейсы выявили ошибку, QA-команда перепроходит эти тестовые случаи вручную.

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

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

Как быть, если утром обнаруживается существенный баг? В этом случае процесс релиза останавливается до исправления ошибки. Если есть возможность исправить ошибку быстро (до конца дня, например), в этой ветке отрезается новый тег, и эта же ветка, но с новым тегом, выпускается на промежуточное окружение, и процесс релиза повторяется снова.

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

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

В целом процесс релиза выглядит следующим образом:

  • Просмотр отчета прохождения автоматических приемочных тестов на тестовом окружении.
  • Запуск упавших и пропущенных тестов вручную.
  • Приёмочное тестирование в промежуточном окружении, который наиболее схож с продовским.
  • Smoke-тестирование на продовском окружении.


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

Роль и обязанности QA-инженера

У вас может сложиться впечатление, что у нас всё так заавтоматизировано, что QA-инженеру больше нечего делать. Но на самом деле, работы достаточно.

  • Во-первых, выяснение и анализ требования. Этим занимаются QA-инженеры – ведь, когда менеджер проекта составляет требования, зачастую упускается очень многое.
  • Во-вторых, оценивание затраты времени на работу с проектом. Когда менеджер проекта спрашивает, сколько нужно времени на написание тестовых случаев, функциональное тестирование и т. п., нужно всё это подсчитать.
  • В-третьих, работа с тестовой документацией, написание тест-кейсов, составление чек-листов и баг репортов.
  • В-четвертых, в нашем проекте проводится функциональное, регрессионное и кросс-браузерное тестирование (т. к. у нас — веб-приложение, и в каждом браузере — свои ошибки).
  • В-пятых, QA-инженеры занимаются поддержкой релиза: каждое утро перепрохождение упавших ночных тестов, а также acceptance- и smoke-тестирование. Но это не значит, что вся команда занята релизом. Релизом заняты люди, у которых меньше приоритетных заданий — наша команда самоорганизующаяся.


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

Также стоит рассказать, чем именно занимаются автоматизаторы в нашем проекте.

Роль и обязанности автоматизатора:

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


Принципы непрерывной поставки


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



1. Процесс релиза и разворачивания должен быть повторяемым и надежным. Однажды запущенный процесс останавливать больше нельзя — даже если вы ничего нового не выпускаете.
2. Автоматизированные тесты должны покрывать 80 – 90 % функционала — без этого процесс не пойдет.
3. Нужно часто проходить тестами по уязвимым местам. Если вы видите, что в каком-то месте у вас часто падают тесты или много ошибок, это место нужно тестировать почаще и убеждаться, что наступают улучшения и что-то исправляется.
4. Качество нужно строить сразу. Это относится не только к разработчикам, но и к тестировщикам. Бывает, что QA-инженеры проверяют баг-репорты на локальных машинах разработчиков, чтобы не допускать попадания не исправленных багов в общей репозиторий. Тогда разработчик исправляет ошибку у себя локально, это гораздо дешевле и быстрее.
5. Каждый несет ответственность за релиз. Благодаря этому, у нас хорошо налажена коммуникация. Если у QA-инженеров, возникают вопросы, мы можем спокойно написать разработчику, и разработчик тоже может нас о чем-то просить.

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

Главное же достоинство непрерывной поставки — довольный заказчик, потому что он может получать то, что хочет, очень быстро, и иметь с этого доход.
Автор: @DataArt
DataArt
рейтинг 144,35
Технологический консалтинг и разработка ПО

Комментарии (39)

  • +2
    Я не понял. У вас что, вся разработка идет в одной ветке?

    Если в разных — то что это за «конфигурационный флаг» и зачем он нужен?
    • +3
      Каждую ночь в случае успешного релиза от trunk отрезается branch
      Сплошная терминологическая путаница.
    • +1
      Возможно, вот описание en.m.wikipedia.org/wiki/Feature_toggle такой техники.
      • +2
        Какой-то кошмар. И это в то время, как давно уже изобрели системы контроля версий.
        • 0
          Хотел ответить с сарказмом, но вот вам четыре крутые плюшки, которые несет фичеризм: 1) Возможность А/В тестов на части пользователей/инстансов, 2) Возможность на проде на 100% убедиться, что на полном окружении все ок, 3) возможность запустить функциональность точно в срок, при этом не дергать программистов и девопсов, 4) возможность выключить функцию без того, чтобы трогать код.
          • +1
            > 1) Возможность А/В тестов на части пользователей/инстансов,

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

            > 2) Возможность на проде на 100% убедиться, что на полном окружении все ок,

            С ветками всё то же самое. Но при этом, если ветка не катит — откатил ветку и всё.

            > 3) возможность запустить функциональность точно в срок, при этом не дергать программистов и девопсов,

            Как и пункт 1 — это не относится к разработке.

            > 4) возможность выключить функцию без того, чтобы трогать код.

            А это повтор пункта 3.
            • 0
              Сильно относится к разработке. Не вижу, откуда вы взяли одну ветку, но там описан механизм отпочкования от транка, который очень похож на git flow (develop->master) с отличиями под их проект. Все преимущества фичеринга к разработке как раз относятся, т.к. один раз сделанная и покрытая тестами задача уходит дальше и ответственность полностью снимается с разработчика и переходит к ответственному за проект.

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

              В общем, недостатки у подхода есть, но гугл так разливает новую функциональность на часть пользователей, так работают с CI в гитхабе — и этот подход хорошо зарекомендовал себя на непрерывных релизах.
              • 0
                Я вижу, что они вместо использования веток используют фичи. А отпочкование от транка используют вместо тегирования. Ветка всего одна — транк.
                • 0
                  Не факт, это просто мое предположение, что хотел сказать автор )
          • 0
            1) Возможность А/В тестов на части пользователей/инстансов
            4) возможность выключить функцию без того, чтобы трогать код.

            var features = require('features');
            
            if (features.has('my_feature')) {
                 ...
            }
            


            features берется из конфигурационного слота или локального конфигурационного файла, в котором определяется процент и группа пользователей.

            2) Возможность на проде на 100% убедиться, что на полном окружении все ок, 3)

            Заведите себе несколько групп тестовых серверов — для разработки, тестирования задачи c различными видами окружений (верстка prod + бекенд dev, верстка dev + бекенд dev), тестирования итерации (верстка tested + бекенд prod, верстка tested + бекенд tested, верстка prod + бекенд tested), тестирования хотфиксов и пр.

            3) возможность запустить функциональность точно в срок, при этом не дергать программистов и девопсов
            Нет никакой связи
            • 0
              Вы на что отвечаете? Ваш код — это и есть фичер тоггл/свитчнры/еще миллион других баззвордов. Именно ради удобства процессов в больших командах и с хорошим континоус фичеризм как раз и используют. Не только для того чтобы иметь возможность откатить изменения, но и например включать / выключать функциональность периодического конкурса (третиц непринятый пункт).

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

              В общем, не понял, с чего вы мне написали. Также, как и не понял, откуда автор предыдущего комментария высосал «одну ветку».

              Мы, например, помимо фич, кучи сред, еще и версионность сервисов используем, и это тоже рождает какое-то количество недостатков вместе с тем профитом, что имеем.
              • 0
                > Также, как и не понял, откуда автор предыдущего комментария высосал «одну ветку».

                А где вы увидели разные ветки?
              • 0
                Вы на что отвечаете?
                В общем, не понял, с чего вы мне написали.

                Вас нет в переписке выше. Это аргументы на конкретные тезизы msnre
        • 0
          Если сравнивать с ветками, то при таком подходе нет необходимости мерджить большие ветки с мастером, следовательно нет конфликтов. Что очень удобно когда над проектом работает очень большая команда.
          Но как и любого подхода у него есть минуса, например увеличивается сложность кода.
          • 0
            Мне интересно, почему фичи нельзя использовать вместе с бранч-топиками и гит флоу, например.
            • 0
              Конечно можно
          • 0
            В мастере никогда не должно быть конфликтов. Это не ветка вливается в мастер, а наоборот, мастер вливается в ветку. Если при этом возникает конфликт, то он разрешается в ветке.

            Затем ветка вливается в мастер, и технически это, конечно, мерж, но конфликта при этом мерже не будет, так-как ветка уже идентична мастеру.
            • 0
              В мастере никогда не должно быть конфликтов.

              В идеальной ситуации не должно быть, но разработчик может «залить» свою ветку над которой он работал долгое время в мастер и уйти на обед/домой/поехать в отпуск не проверив.
              • +2
                Не может такого быть. Это аналогично ситуации, когда уборщица в кабинете директора взяла и подписала документы.

                Никакие коммиты в мастер заливать нельзя. Любые правки попадают в мастер только через мерж-реквесты, которые, в свою очередь, должны быть протестированы, проверены на конфликты, зааппрувлены и.т.д и.т.п.
      • 0
        Статья от Фаулера
    • 0
      Фичеринг.
    • 0
      Есть транковые окружения, на которых идет процесс разработки. Скажем, их версия — 0.200, тогда версия бранча — 0.199. Т. к. релиз каждый день, и каждую ночь от транка отрезается бранч, изменения, которые были в транке, будут в бранче, т. е. версия транка будет уже 0.201, а бранча — 0.200. Чтобы скрыть код для неготового функционала, нужен конфигурационный флаг. По сути, на момент релиза какой-либо фичи код уже находится в продакшн, просто он скрыт.
      • 0
        Ну т.е. вся разработка ведется в одной ветке — в транке.
  • 0
    Сначала получаем требования, после чего QA-команда, проанализировав и выяснив требования, начинает писать тест-кейсы. В это же время идет процесс разработки. После того как разработчики, дав добро на тестирование, включают конфигурационный флаг на тестовом окружении, QA-инженеры начинается функциональное тестирование. Пока QA-инженеры тестируют и находят ошибки, которые разработчики исправляют, автоматизаторы или Selenium-команда (так мы их называем), начинают процесс автоматизации тест-кейсов. После функционально тестирования проводится регрессионное тестирование.
    Вы меня окончательно запутали.
    • 0
      Ага.

      После функционально тестирования проводится регрессионное тестирование.


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

        PS: Кажется я начинаю понимать автора. В следующим раз, DataArt вам следует писать статью коллективно и хотя бы проверять на опечатки.
  • 0
    Спасибо за статью, читал с интересом.
    Планируете ли переход к continuous deployment, как к следующему шагу?

    И да, в терминах путаница, в статье идет речь о QC, а не QA инженерах.
  • +14
    С ежедневными релизами у меня только такие ассоциации. Извините.
    image
  • +2
    Не хотел бы я у вас работать. Как бы там ни было всё автоматизировано, ежедневный релиз — это ежедневный стресс. Что разработчики, что тестеры крутятся как белки в колесе, чтобы не дай бог что не отвалилось, не пролезли баги в релиз. Ни передохнуть, ни поэкспериментировать. Как роботы. После месяца такой работы надо давать неделю отпуска как минимум.
    • –5
      А я не уверен, что там стресс.
      Просто разработчик что-то изменил/добавил несущественное и закачал измененный файл в репозиторий, а он автоматом собрался и зарелизился.
      Только вот каково это для пользователя, получать каждый раз новые релизы? Не надоедает?
    • +4
      Какой еще стресс? У нас релизы не то, что ежедневные, а вообще по 10 штук в день. Каждый коммит — это релиз.

      Как-раз CI позволяет превратить всё это в обычную повседневную работу, без всякий «ах, офигеть, сегодня релиз, это бля, целое событие!».
      • 0
        Ну это если 100% покрытие тестами, да и тесты действительно умер написаны.
    • 0
      Мне кажется стресс — это когда выкатываешь огромный релиз и с тревогой ждешь, что вывалится такая же огромная куча багов. Проще релизить маленькими порциями каждый день.

      На ум приходит аналогия между обновлением дистрибутивов Linux:
      • Ubuntu: как часто бывает — обновился до новой версии, сломал все.
      • ArchLinux: rolling release, система постепенно обновляется маленькими порциями
    • 0
      У нас всяких проектов хватает, на любой вкус.
  • 0
    Давайте вещи называть своими именами. Не релизы ежедневные, а тесты. Сами же написали:

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


    и

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


    Так что — дань моде и модным словечкам это, конечно, хорошо но не стоит увлекаться. С точки зрения бизнеса частые релизы не нужны — никакой заказчик себе каждый день в бой новую версию заливать не станет. Исключением является ситуация профуканных дедлайнов, тогда да, возможность представить хоть что-то спасёт немало менеджерских задов.
  • 0
    1) Когда пишутся тесты на новый функионал
    2) Какого уровня эти тесты, приведите пример (Например после авторизации есть кнопка на форме или что-то более серьезное)
    3) Как описываются функциональные тесты с бизнес-логикой?
    • 0
      Тестовые случае пишутся после того как были получены и проанализированы требования, т. е. параллельно процессу разработки. Сложность тест-кейсов зависит от того, какой функционал они покрывают.
      Требования предоставляются заказчиком исходя из потребностей бизнеса, а тест-кейсы уже непосредственно покрывают эти требования. На одно требование может быть написано несколько тестовых случаев.
      • 0
        Приведите, пожалуйста, пример тест-кейса на бизнес-функцию с математикой, правами доступа итп обезличенный если есть секреты.
  • 0
    Всем, кто считает, что ежедневные релизы — стресс, скажу уверенно «нет». Работа в таком проекте очень интересная, т. к. все развивается очень стремительно. К этой модели разработки мы пришли не сразу, переход был длительным и трудоемким, но успешным. Заказчик доволен, а это в нашем деле очень важно.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка