Ускоряем разработку: стандартный способ “в лоб” и более эффективный способ “сначала немного подумав”

В этой статье мы опять поговорим про разработку, а конкретнее про то, как можно подходить к задаче от бизнеса об уменьшении time to market разрабатываемых фич. Обычно это один из злободневных вопросов, который ставят разнообразные C*O перед CTO.

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

  • Chief Product Officer (Главный за Продукт) — назовем его Петей
  • Chief Technical Officer (Главный за Технологии) — назовем его Толей
  • Quality Assurance Head (Главный за Качество) — назовем его Колей
  • SW Development Head (Главный за Разработку) — назовем его Ромой

Теперь, когда основной сетап готов, можно начать рассказывать историю, для которую я проиллюстрировал картинкой с Рис.0 (у меня как принято у программистов и нумерация картинок начинается с нуля в этой статье).

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

Ускорение релизов

Сетап задачи

Наш технический директор Толя приходит к своим руководителям разработки и тестирования и предлагает придумать схему как можно ускориться. Коля, отвечающий за качество, и Рома, отвечающий за разработку, сообщают Толе, что фичи они пилят максимально быстро, а регресс релизной ветки обычно занимает полную рабочую неделю. Они говорят, что так исторически сложилось, что тестирование приложения всегда имело преимущественно ручной характер и только в последнее время они начали задумываться о автоматизации тестирования. Но автоматизация — это дело небыстрое, поэтому Коля и Рома предлагают попробовать ускорить релизы вручную на морально-волевых качествах текущих разработчиков и qa-инженеров. Толя соглашается и появляется план ускорить релизы в 2 раза и довести их частоту до раза в 2 недели. Ниже приводится результат такого ручного ускорения (spoiler: оно плачевное), а после этого приводится вариант более эффективного подхода к увеличению скорости разработки.

Ускорение релизов на ручном приводе с мануальными регрессами

Теперь давайте разберем что получится в этом случае с трудозатрарами. Пускай для определенности в команде разработки есть суммарно:

  • 12 разработчиков
  • 4 qa-инженера

Состав команды представлен на рисунке ниже

Рис.1 “Состав команды”

Если суммировать общий ресурс разработки и тестирования, то в 4 недели умещается 48 человеко-недель разработки и 16 недель тестирования. Если у нас релизы раз в четыре недели, а регресс занимает неделю, то логично предположить, что всю эту неделю все 4 qa-инженера тратят на проведение регресса. Это значит, что мы в этом случае тратим 4 человеко-недели на тестирование. Это составляет четверть всех ресурсов тестирования. В это же время регресс сопровождают разработчики, которые выступают дежурными и фиксят найденные баги, которые надо срочно починить для того, чтобы приложение можно было зарелизить. Я предположил, что на сопровождение релиза и устранение багов разработчики тоже тратят 4 человеко-недели. Получается, что регресс отнимает 1/12 ресурса разработки и 1/4 ресурса тестирования.

Рис.2 “Относительные затраты на регресс раз в 4 недели”

Теперь мы включаем релизы раз в две недели, а регресс занимает неделю, то логично предположить, что всю эту неделю все 4 qa-инженера тратят на проведение регресса. Здесь весь цимес в том, что в общем случае время регресса не зависит от размера релиза (в частных случаях с нормальной декомпозицией технического продукта на части это не так). В итоге, за тот же календарный промежуток в 4 недели мы уже тратим 8 человеко-недель на тестирование, что составляет уже 50% от всех ресурсов тестирования. В это же время регресс сопровождают разработчики, которые выступают дежурными и фиксят найденные баги, которые надо срочно починить для того, чтобы приложение можно было зарелизить. Я предположил, что на сопровождение релиза и устранение багов разработчики тоже тратят 8 человеко-недель. Получается, что регресс отнимает 1/6 ресурса разработки и 1/2 ресурса тестирования.

Рис.2 “Относительные затраты на регресс раз в 2 недели”

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

Ускорение релизов с автоматизацией регрессов

Проведя указанный ваше эксперимент в реальности или виртуально, наши руководители от разработки (Толя, Рома, Коля) решают, что повышать частоту релизов при сохранении ручного регресса не получится. Но на помощь уже спешит автоматизация тестирования. Они решают начать с автоматизации проверки регресса за счет end to end тестов, так как

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

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

Здесь есть несколько основных подводных моментов:

  • end-to-end тесты тестируют как запрос обрабатывается цепочкой систем
  • эти тесты обычно часто мигают, то есть выдают ложноположительные срабатывания о наличии проблем, так как связанные системы могут не отличаться стабильностью
  • для end-to-end тестов нужна инфраструктура, которая позволит поднять дополнительный стабильный контур, на котором можно прогонять весь набор регресс-тестов никому не мешая и самому не страдая от шумных соседей
  • обычно эти тесты занимают довольно длительное время

Обычно, если компании основывают свой подход к автоматизации обеспечения качества на написании большого количества end to end тестов в ущерб более быстрым и атомарным проверкам, то ничем хорошим это не заканчивается и чуть позже я объясню почему. Но пока представим, что автоматизировать проведение регресса удалось большим количеством end-to-end тестов. Теперь qa-инженеры тратят время на поддержание тестов актуальными + разбор падений.

Кстати, на приведенном ниже рисунке показан сквозной запрос через 14 систем. Если эти 14 систем на тестовом конутре будут работать каждая с доступностью не порядка 95%, то вероятность успешного прохождения теста будет меньше 50%. А если быть точнее, то получаем

Особого смака добавляет тот факт, что зачастую end-to-end тесты реализованы таким образом, что не получится просто установить причину проблем . То есть падение теста приводит к сложному процессу определения какая из этих 14 систем работала не так как ожидалось в тесте, а после уже определения реальная ли была проблема или проявилась нестабильность стенда конкретно этого элемента цепочки.

Рис.4 “Сквозной запрос через 14 систем”

В итоге, предсказать итоговый эффект автоматизации регрессов сложно, но давайте предположим, что их удалось ускорить. Но … в этот момент Роме, нашему руководителю разработки, приходит отличная идея — запускать эти тесты не только для проверки релизных веток, но и для pull request’ов, которые делают разработчики во время разработки фич. Это позволит еще увеличить time to market за счет того, что разработчики будут получать информацию о том, что фича не работает не от qa-инженера после передачи задачи в Testing, а гораздо раньше. Так открывается следующий шаг.

Ускорение разработки

Перевернутая пирамида тестов

Если Рома решит в лоб подключить End to End в качестве одного из шагов Continuous Integration пайплайна, то его ждет большое разочарование. В таком режиме возникнет несколько проблем:

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

В общем, в этом случае наши руководители от разработки (Толя, Рома, Коля) окажутся в ситуации “Пирамиды тестов курильщика”, изображенной ниже, где площадь подписанных частей рисунка обозначает количество тестов. Слева показана перевернутая пирамида, в которой основание почти отсутсвует и основная масса тестов сконцентирована вверху. Пирамида тестов “здорового человека” расположена справа, причем уровней разные люди выделяют разное количество, но основной смысл ясен при любом количестве уровней.

Рис.5 “Пирамида тестов курильщика и здорового человека”

Правильная пирамида тестов

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

  • нормально декомпозировано на подсистемы
  • у подсистем есть нормальный API
  • есть описание автоматизируемого бизнес-процесса и участвующих во всей цепочки систем
  • есть нормальная инфраструктура, позволяющая развернуть контур для end to end тестирования

В общем, если этих штук нет, то зачастую тестировать систему можно только как черную коробку как раз end to end тестами.

Как сделать правильно

По-моему, для Толи изначальную задачу снижения time to market стоило поделить на 4 направления:

  • Архитектура программной системы
  • Тестирование
  • Инфраструктура
  • Процессы разработки

Архитектура

Здесь требуется получить в итоге четкую и понятную декомпозицию системы на части, которые являются некоторыми функциональными компонентами. У этих компонентов должны быть четко определенные интерфейсы использования. Компоненты должны сопровождаться документацией и иметь предусмотренные точки расширения. При создании таких компонентов, стоит настроить им CI/CD pipeline отдельно, чтобы при изменении этих компонентов прогонялись их тесты и публиковались артефакты (подробнее про наш опыт во фронте можно почитать здесь)

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

Это направление — ответственность Ромы, руководителя разработки.

Тестирование

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

Также Коле надо договориться c Ромой о том, какие они пишут тесты и в какой пропорции. Кто именно пишет тесты: только тестировщики или/и разработчики (очень рекомендуется смешанный вариант). Какие именно тесты пишутся и при помощи каких инструментов.

Инфраструктура

Параллельно с обдумыванием того, какие тесты пишутся и кем, нам надо понять где все это будет исполняться. Толе стоит подумать над инфраструктурной командой, которая выстроит автоматизацию процессов, а именно построение полноценного CI от сборки билдов(обычно это артефакты) до запуска всех наших тестов. Это зона человека, который отсутствует в изначальном сетапе задачи.

Процессы разработки

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

  • надо чаще сливать код из фиче-бранчей в общую ветку (для мобилок если задача еще не готова, то можно использовать feature toggles для ее экранирования, для этой возможности, кстати, нужна правильная архитектура, а для веба можно использовать сервисную архитектуру и пилить функционал в отдельных сервисах)
  • надо иметь специфицированный процесс подготовки релиза — с указанием всех шагов, участвующих ролей и их ответственности

Общее руководство

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

Director of digital ecosystem development department at Tinkoff. Bachelor at applied math, Master at system analysis, Postgraduate studies at economics.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store