Наша цель — обеспечить, чтобы разработчики и тестировщики регулярно интегрировали код в среду, близкой к производственной, с интервалами, постепенно сокращающимися по мере выполнения проекта[72]. Мы делаем это путем расширения определения «выполнено» за границы правильного функционирования кода: в конце каждого интервала разработки мы должны иметь интегрированный, протестированный, работающий и потенциально готовый к поставке код, указанные характеристики которого продемонстрированы в среде, близкой к производственной.
Другими словами, мы будем считать задачу разработчиков выполненной, если она будет успешно собрана, развернута и подтвердится, что она работает, как и ожидалось, в среде, близкой к производственной, а не тогда, когда разработчик считает ее сделанной. В идеале она работает в среде, близкой к производственной, с набором данных, близким к производственному, задолго до окончания спринта. Это предотвращает ситуации, когда функцию называют сделанной лишь потому, что разработчик может успешно запустить ее на своем ноутбуке и нигде больше.
За счет того, что разработчики могут писать, тестировать и запускать код в среде, близкой к производственной, успешная интеграция кода и среды происходит во время повседневной работы, а не в конце релиза. К концу первого интервала можно продемонстрировать, что приложение правильно работает в среде, приближенной к реальной, что код и среда были интегрированы уже много раз, и в идеале полностью автоматизировано (никакой правки вручную не потребовалось).
Что еще лучше: к концу проекта мы успешно развернем и запустим код в средах, близких к производственным, сотни или даже тысячи раз, и это даст уверенность, что большинство проблем при развертывании продукции найдены и устранены.
В идеале мы можем использовать такие же инструменты — мониторинг, журналирование и развертывания — в предпроизводственных средах, как делаем это в производственных. Поступая так, мы приобретаем осведомленность и опыт, помогающие беспрепятственно развернуть и запустить сервис, когда он окажется в производственной среде, а также диагностировать проблемы и устранить их.
Дав возможность разработчикам и группе эксплуатации приобрести общее знание того, как взаимодействуют код и среда, попрактиковаться в ранних и частых развертываниях, мы значительно снижаем риски развертывания, связанные с релизами кода продукта. Это также позволяет нам избавиться от целого класса дефектов эксплуатации и безопасности, архитектурных проблем, которые обычно проявляют себя, когда уже бывает слишком поздно, чтобы их исправлять.
Быстрый поток работы от разработчиков к группе эксплуатации подразумевает: любой работник по первому требованию может получить среду, приближенную к производственной. Дав разработчикам возможность использовать ее уже на самых ранних этапах проекта создания программного обеспечения, мы значительно снижаем риск появления производственных проблем впоследствии. Это один из многих методов, демонстрирующих, как отдел эксплуатации может сделать труд разработчиков гораздо более продуктивным. Мы закрепляем у разработчиков практику запускать код в условиях, близких к производственным, включая это условие в определение состояния «Закончено».
Более того, передавая производственные артефакты под управление системы контроля версий, мы получаем «единственный источник истины», что позволяет пересоздавать производственную среду быстро, повторяемо и документируемо, применяя к отделу управления те же методы работы, что и к разработчикам. А поскольку создать производственную структуру заново оказывается более легким делом, чем восстанавливать ее, решать проблемы удается быстрее и проще. Увеличивать мощность сервиса также становится легче.
Применение этих методов в правильных местах создает основу условий для всеобъемлющей автоматизации тестирования, которая рассматривается в следующей главе.
Глава 10. Быстрое и надежное автоматизированное тестирование