Перенос стадии тестирования на ранние либо поздние этапы жизненного цикла разработки может способствовать скорейшему достижению поставленных целей или существенно повлиять на улучшение самого процесса разработки. Как же понять, когда стоит вносить изменения в привычный порядок циклов разработки программного обеспечения? Пусть ответом на этот вопрос станут ваши циклы тестирования. Что мы имеем в виду? Хорошим наглядным примером служит вождение автомобиля с механической коробкой передач. Если двигатель автомобиля «воет» на повышенных оборотах либо готов вот-вот заглохнуть из-за слишком низких оборотов, опытный водитель и без подсказки поймет, что в этой ситуации поможет только переключение передачи.
Сейчас уже многие говорят о переносе процесса тестирования на ранние стадии разработки. Как же так? Ведь всего лишь несколько недель назад тестирование двигалось вправо, ближе к концу жизненного цикла. Где вы сейчас? Не стоит размышлять о переносе тестирования на ранние либо поздние этапы, без осознания его текущей позиции.
Впрочем, вначале давайте рассмотрим преимущества раннего и позднего тестирования, с учетом того, какие потребности будут покрыты или, что будет улучшено за счет такого смещения.
Чтоб последующая информация воспринималась легче, давайте-ка добавим немного визуализации. Поскольку мы уже упоминали автомобильную коробку переключения передач, представьте ее в виде набора из пяти шестерен с разным количеством зубьев на каждой.
Классика жанра: третья передача
Увы, но это текущее положение вещей в большинстве компаний. На этапе разработки проводятся только основные и технические проверки. Есть специальная система тестирования, в которой и выполняется проверки качества продукта. Все как обычно: разработчики пишут код, а тестировщики проверяют функциональность продукта, в том числе в связке с другим софтом.
Тестируемые приложения «упакованы» таким образом, что общаются друг с другом только посредством специально разработанного функционала, как правило, с ограниченными возможностями. Несмотря на то, что подобная конфигурация довольно-таки статична, для ее поддержки и обслуживания требуется «тонна» усилий, глубокое понимание принципов работы каждого отдельного продукта, знание применяемых технологий и общих принципов рабочего процесса. Поскольку каждое приложение связано с определенной командой разработчиков (иногда даже находящихся в разных компаниях), то в случае появления «багов» вы сильно зависите от того парня, который непосредственно написал проблемный код. А что если сейчас он недоступен? Тогда у вас проблема! Выход продукта на рынок снова откладывается, поскольку нужная вам информация пока недоступна.
Однажды мы сотрудничали с банком, который использовал специальную систему, сконфигурированную таким образом, чтобы тестирование выполнялось на каждом этапе разработки. Тестовые случаи включали ситуации с воссозданными проблемами, раннее выявленными в процессе работы приложения.
Проблемные кейсы включали несогласованность тестовых данных в системах, различия между рабочими средами систем или этапов, а также некоторые ошибки, появляющиеся только при определенных конфигурациях. Большая часть времени, отведенного для тестирования, приходилось на настройку систем и выстраивания их в нужной последовательности, которая, как предполагалось, отвечала бы реальной ситуации.
Базу тестовых данных можно было просто импортировать. Она была полезной еще и потому, что позволяла легко создавать пользователей и учетные записи, подставляя «на лету» любые даты, иначе тестирование заняло бы годы. Есть ли способ получше?
Сдвиг влево: Первая передача
Почему мы привыкли к тому, что в жизненном цикле разработки тестирование проходит на поздних этапах? Ведь это же очевидный факт – чем раньше найдена ошибка, тем проще и дешевле обходится ее исправление. Давайте-ка сдвинем этап тестирование влево по временной оси жизненного цикла разработки программного обеспечения, и переместим его в среду разработки.
Благо, что из-за существенных изменений в конфигурациях, провернуть это дельце сейчас уже не так хлопотно, как раньше. Системы мигрировали в облачные сервисы, а тестировщики перешли к использованию API. Работая в среде, контролируемой на уровне API, каждое приложение может вызвать функцию (универсальную или выделенную) в обход службы, чтобы выполнить более раннее тестирование. После окончания проверки данные передаются через запрос для формирования ответа. Если требуемая система недоступна, этот вопрос решает служба виртуализации (service virtualization).
Служба виртуализации — это простой, но действенный способ для проведения всесторонних испытаний любой подключенной системы, позволяющий тестировщикам «играть» с ней по своим правилам. Виртуализация также помогает создавать сложное окружение, чтобы обучение проходило в обстановке, «приближенной к боевой», а полученная практика уменьшала риски возникновения непредвиденных ситуаций. Тем более, что для последующего воспроизведения требуемых ситуаций, все потоки данных записываются. Вызовы служб выполняются на уровне API и служба виртуализации ведет себя так же, как вел бы себя готовый продукт (система).
Модульный подход к тестированию также вносит свои изменения в правила игры. Разработчики создают модули, которые после используются тестировщиками. Просто представьте перспективы тестируемой системы, в которой разработчик видит только ее часть, а тестировщики видят картину системного «ландшафта» целиком и со всеми возможными конфигурациями. Повторное использование некоторых артефактов создаст новые цепочки процессов либо добавит новые возможности в процесс моделирования. Разработчики могут определить обязательные параметры подключения, такие как логины, пароли, конечные точки и минимально необходимые меры безопасности, а тестировщики просто берут все это и используют в тестовой среде (да-да, именно среде, а не выделенной области тестирования, в которой системы реально взаимодействуют друг с другом без виртуализации.)
Тестовые данные и варианты всех тестов могут быть доступны и для dev- и для test-команд поэтому в зависимости от важности конкретного теста, он может быть запущен уже на этапе разработки, с последующей записью входящих/исходящих данных. Вызов службы можно осуществить типичным способом, но это зависит от данных, которыми оперирует команда. Поиск ошибок на ранних стадиях жизненного цикла приводит к уменьшению ресурсов, выделяемых для последующего тестирования, и ускоряет время выхода продукта на рынок.
Однажды мы участвовали в переносе тестирования на ранние стадии в компании, занимающейся обслуживанием кредитных карт. Хотя в то время им уже удалось избавиться от статической конфигурации тестов и перейти к API, но, несмотря на всю специфичность софта и функционала, на ранней стадии тестирования было выявлено очень много ошибок. Компания располагала отдельной командой тестировщиков, которая просто фокусировалась на уровне API и проверяла связь между ним и приложениями. Тестировщики вместе с разработчиками создавали модули, предоставляющие запросы и ответы. Одни и те же модули использовались повторно при тестировании системы с разными параметрами соединений. Это экономило огромное количество времени, так как команда разработчиков знала, что будет нужно тестировщикам в случае внесения определенных изменений в параметры соединений. Критичные ошибки и нестыковки данных были выявлены еще на этапе разработки и были решены поэтапно, во время развернутого тестирования.
Когда они еще только начали «истязать» приложение с помощью служб виртуализации, разработчики уже успели рассказать нам, как далеко смогут зайти их проверки, чем существенно сэкономили время дальнейшего тестирования и обслуживания.
Сдвиг вправо: пятая передача
Этот особенный метод, потому что мы попытаемся получить лучшее из обоих техник, рассмотренных выше. На этом этапе существенно увеличивается количество тестировщиков, но время выхода на рынок должно сократиться, потому что тестирование происходит в продакшене.
Одним из лучших примеров смещения тестирования вправо (shifting right) является Amazon, так как его заказчики и потребители также выступают в качестве тестировщиков. Все операции глубоко интегрированы. Оптимальный результат достигается в том случае, когда стадия раннего тестирования уже пройдена и на выходе у вас остается только финальный продукт, который проходит автоматическую сборку.
Для того чтобы провести надлежащее тестирование в продакшене, придется потратить больше усилий, чем на предыдущих этапах, потому что все процессы должны быть настроены идеально, а работа – автоматизирована в пользу уровня API. Все, что вы забыли проверить, будет присутствовать в производстве, поэтому функциональность, которая не была покрыта тестами, может привести к реальным проблемам. Ваш продукт должен уже быть сверхстабильным и, возможно, работать с ограниченным числом подключений. По крайней мере, позаботьтесь о том, чтобы все было протестировано с не менее чем 90 % покрытием рисков, иначе некоторые операции не смогут развернуться.
Каждый модуль должен обрабатываться независимо. Полное развертывание в рабочей среде должно состоять из множества фрагментов, так как это обеспечит лучшее покрытие тестами. Большинство фич могут вызвать побочные эффекты. Их может быть даже больше ожидаемого, поэтому их нужно включить в ваши тесты как можно раньше. Конечно, финальное тестирование выполнят непосредственно пользователи, а их отзывы приведут вас к оставшимся ошибкам.
Несмотря на вышесказанное, необходимо не забыть о готовом рабочем конвейере непрерывной интеграции QA, который будет запускаться во время сборки. Большинство тестов запускаются автоматически, во время работы, выбранной CI-тулзы, поэтому сборка выполнится только в случае их успешного прохождения. Тестировщикам нужно позаботиться только о создании тестов, их поддержке и проверке результатов. Идеально, если тестировщики еще и умеют распознавать ложные срабатывания, а также оценивать необходимость вовлечения в процессы тестирования или разработки.
Если вам удалось пройти через все «передачи» воображаемой коробки передач, то вы должны использовать преимущества первой. Здесь модули API могут использоваться повторно, а обслуживание на техническом уровне выполняется только один раз. Качество конечного продукта будет оценено клиентами на основании их отзывов (речь идет о сообщениях-разочарованиях).
Этот способ подходит для увеличения лояльности пользователей и для создания функционала, отвечающего их требованиям, но, чтобы воспользоваться им, нужно, чтобы ваш продукт уже находился на определенном уровне. Если новые «фишки» не слишком сильно повлияют на ваш бизнес, в том смысле, что частота их использования, как и возможный ущерб, несущественны, можно смело экспериментировать в этом направлении. В противном случае постарайтесь убедиться, что тесты покрывают как можно больше функциональности, а все побочные эффекты обнаружены. Чем выше плотность тестового покрытия, тем выше доверие к продукту.
Ранее мы настраивали этот процесс для одного из крупных ритейлеров. Их продукт был уже почти готов и как раз проходил стадию наполнения фичами. Каждое приложение, созданное сторонней командой, виртуализировать и подключалось через API. Каждая сборка проходила через конвейер CI и проверялась на стороне разработчика с помощью автоматизированных API-тестов и JUnit.
Если все «Ok», сборка автоматически перемещалась в специальное тестовое окружение. Там с помощью CI-тулзы в сборку включались тестовая среда и инструменты тестирования, после чего она пересобиралась. Потом запускались автоматизированные функциональные тесты, во время которых использовались UI, API и реальные устройства. Если результаты прохождения тестов «зеленые», сборка передавалась в продакшен и собиралась автоматически. С одной стороны, вы сильно сэкономите время и деньги, с другой — должны быть уверены в используемых системах и приложениях.
В случае необходимости внесения изменений в тесты вам нужно будет работать всего лишь с одним продуктом, что также сильно снимает «головную боль». Благодаря заранее встроенным модулям, не придется создавать одни и те же тесты для разных окружающих сред, но главная проблема – это «ровная» работа виртуализации на различных этапах. При создании тестового набора мы даже ввели принцип “четырех глаз”, чтобы убедиться в том, что все проверено и покрыто тестами.
Не бойтесь использовать передачи
Каждое тестовое окружение зависит от многих факторов, включающих команду, само приложение и конфигурацию инфраструктуры. На разных этапах могут использоваться различные тестовые стратегии и подходы. Если в процессе тестирования вы думаете, что переход вправо либо влево мог бы быть полезнее, либо сам ход процесса «толкает» вас в определенном направлении — сделайте это.
Каждый сдвиг — это целый процесс, а не одно мгновение. Не бойтесь переносить тестирование на разные стадии жизненного цикла программного обеспечения, если считаете, что это принесет больше пользы для общего дела. И, да, мысли о создании совершенно нового плана тестирования всегда будут останавливать вас. Не позволяйте им делать это. Возможность повторного использования теста очень высока, поэтому однажды применив что-то на «третьей передаче», вы можете сэкономить много времени и денег на пятой.
Пусть ваши тестовые циклы сами наталкивают вас на верный путь, подобно тому, как звук мотора автомобиля, с механической коробкой, наталкивает водителя на мысль о необходимости переключить передачу.