- PVSM.RU - https://www.pvsm.ru -
Здравствуй! Сегодня я хочу завершить цикл статей об организации тестирования (начавшийся с изучения ошибок [1] и опыта [2]), рассказав о том, как же все-таки Badoo выпускает два качественных серверных релиза каждый день. Кроме пятницы, когда мы релизимся только утром. Не надо релизиться в пятницу вечером.
Я пришел в Badoo чуть более четырех лет назад. Все это время наши процессы и инструменты для тестирования непрестанно развивались и совершенствовались. Для чего? Число разработчиков и тестировщиков увеличилось примерно в два раза — значит, для каждого релиза готовится больше задач. Количество активных и зарегистрированных пользователей тоже удвоилось — а значит, и цена любой нашей ошибки стала выше. Для того чтобы доставлять пользователям максимально качественный продукт, нам нужны всё более и более мощные средства контроля качества, и эта гонка не заканчивается никогда. Цель этой статьи не только продемонстрировать работающий пример, но и показать, что какими бы крутыми ни были ваши процессы контроля качества, наверняка можно сделать их еще лучше. Технические реализации некоторых инструментов вы сможете найти по ссылкам на другие статьи, о некоторых из них нам еще предстоит написать.
В Badoo существует несколько разных QA-флоу, отличие которых обосновано разными средствами разработки и целевыми платформами (но мы используем для них общие системы: JIRA, TeamCity, Git и т.д.), и я вам расскажу о процессе тестирования и деплоя наших серверных задач (а заодно и веб-сайта). Его можно условно разделить на 5 больших этапов (хотя тут, конечно, многие мои коллеги считают по-разному), каждый из которых включает в себя и ручную, и автоматизированную составляющую. Постараюсь рассказать вам по очереди о каждом из них, отдельно выделяя то, что изменялось и развивалось в последние годы.
Да, не удивляйтесь, это вообще-то тоже этап контроля качества. Он придуман для того, чтобы в боевой код не попадали архитектурные и логические ошибки, а задача никоим образом не нарушала наши стандарты и правила.
Код ревью у нас начинается в автоматическом режиме еще до того, как разработчик «запушит» свой код в общий репозиторий. При попытке сделать git push на принимающей стороне запускаются pre-receive хуки, которые делают огромное количество различных вещей:
Провал любой из этих проверок приводит к запрету на пуш, и разработчику необходимо исправить возникнувшие замечания. Подобных хуков постоянно становится все больше и больше.
А помимо pre-receive хуков у нас есть и растущий пул post-receive хуков, которые выполняют множество операций, автоматизирующих наши процессы: изменяют поля и статусы задач в JIRA, запускают тесты, дают сигналы нашей системе деплоя… В общем, они очень большие молодцы.
Если код смог прорваться через все этапы автоматической проверки, то он добирается до ручного code review, который проводится на базе сильно модифицированной нами версии GitPHP [3]. Коллега-разработчик проверяет оптимальность и соответствие решения задачи принятой архитектуре, общую корректность бизнес-логики. На этом же этапе проводится проверка покрытия нового или измененного кода юнит-тестами (задачи, не покрытые тестами в должной мере, ревью не проходят). Если же во время решения задачи был затронут код других отделов, то их представители обязательно присоединятся к ревью.
Прямо в GitPHP ревьюер может делать комментарии к коду — и они все отобразятся в качестве комментариев в соответствующей задаче в JIRA, а QA-инженер сможет проверить исправление всех замечаний при тестировании (разработчики даже иногда устраивают холивары в этих комментариях, читать — одно удовольствие).
Что такое в нашем понимании «девел-окружение»? Это полноценная платформа, максимально копирующая архитектуру продакшена в меньших масштабах, предназначенная для разработки и тестирования. Девел содержит свои собственные базы данных, собственные копии демонов, сервисов и CLI-скриптов. Он даже разбит на две полностью отдельные площадки для тестирования их взаимодействия: одна находится в московском офисе и эмулирует работу нашего пражского дата-центра, вторая — в лондонском, эмулирует работу дата-центра в Майами.
В рамках девела для каждого разработчика и тестировщика выделена собственная «песочница», куда он может выгружать любую необходимую ему версию кода сервера и которая доступна из нашей внутренней сети по соответствующему URL. Разворачивать каждому разработчику свою собственную песочницу на локальной машине, к сожалению, слишком накладно: Badoo состоит из слишком большого количества различных сервисов и зависит от конкретных версий ПО.
Было бы здорово, если бы сразу же после того, как разработчик закончил работу над задачей, в ней запускались хотя бы интеграционные и юнит-тесты, правда? Сейчас я вам расскажу одну небольшую историю отчаянной борьбы.
Запуском тестов в нужных ветках в нужный момент занимается наша незаменимая помощница AIDA [8] (Automated Interactive Deploy Assistant), разработанная нашими релиз-инженерами. На самом деле, большая часть всех автоматизированных процессов при нашей разработке не обходится без ее нежных (хоть и достаточно костлявых) рук.
Итак, тестировщик наконец-то получает на руки задачку. Все юнит-тесты в ней прошли, можно приступать к тестированию. Что же нужно делать? Правильно, надо воспроизводить все нужные кейсы. И 4 года назад это было очень унылое занятие.
Badoo — сервис знакомств, а значит, весь функционал сильно зависит от пользователя. Практически для каждого теста (а по-хорошему — и для каждого кейса) нам нужно регистрировать свежего пользователя. Поскольку большая часть функционала закрыта для пользователей без фото, то нужно еще и загрузить (и промодерировать) несколько фотографий. В сумме это уже занимает минут 5 рутинной работы.
Затем нужно подготовить тестовые данные. Мы хотим увидеть промо-окошко, отображаемое пользователю, который за сутки написал сообщение сотне других пользователей? Что ж, разминаем пальчики и начинаем флудить. И плакать.
О, для этого кейса нужен пользователь, зарегистрированный более года назад? У меня такого нет :( Ребят, а у вас есть у кого-нибудь? Нет? :((( Придется идти дергать разработчиков, чтоб они подправили значения в базе данных…
Очень печальная история, не находите? Но к нам пришло спасение— QaApi [9]! Что это такое? Это замечательная система, которая позволяет с помощью http-запросов производить различные действия на серверной стороне (разумеется, все это прикрыто авторизацией и может аффектить только пользователей, которые помечены как тестовые. Не надо пытаться отыскать этот интерфейс у себя дома).
QA-инженер может сделать простенький запрос на QaApi (вида qaapi.example.com/userRegister [10]), GET-параметрами передать нужные настройки (пол пользователя, город регистрации, возраст и т.д.) и в ответ сразу же получить авторизационные данные! Причем таким образом можно получать пользователей как на девел-окружении, так и на продакшене. В то же время мы не засоряем наш продакшен ботами, тестовые пользователи не отображаются живым, а вместо регулярной регистрации пользователей мы получаем подходящего (и уже полностью очищенного после предыдущих тестов) пользователя из пула, если такой уже есть.
Такими же простыми запросами можно изменять и заполнять различные данные, недоступные к изменению из интерфейса: уже упомянутую дату регистрации, количество новых контактов или лайков за сутки (ура!) и все что только душе угодно. А если для изменения нужного параметра нет QaApi-метода? Чаще всего для его добавления достаточно базовых знаний PHP и это может сделать любой инженер! Иногда, впрочем, требуются более глубокие правки в коде, и тогда приходится обращаться к ответственным за компонент разработчикам.
Естественно, вся эта красота была придумана не только для ручного тестирования. Наши тесты тоже стали вовсю использовать QaApi: тесты стали быстрее и атомарнее, тестируют только то, что действительно должны тестировать (разумеется, отдельные тесты на упрощаемые таким образом операции тоже есть).
А когда мы решили, что и этого недостаточно, то реализовали QaApi-сценарии, которые позволяют писать на Lua (не спрашивайте) простые скрипты, которые посредством вызова различных методов в один клик подготавливают даже сложные данные для тестирования сложных кейсов.
Помимо способов оптимизировать и автоматизировать тестирование на девеле, конечно же, очень важны способы сделать его максимально полным и приближенным к продакшену.
Например, CLI-скрипты. Раньше они запускались с помощью крона. Соответственно, если тестировщик хотел проверить новую версию какого-нибудь скрипта, он должен был сделать следующее:
Пропуск любого из этих этапов приводит к проблемам либо для самого тестировщика (может работать не та версия скрипта, которую он ожидает), либо для всех окружающих (скрипт не работает и никто не знает, почему).
Сейчас же у нас таких проблем не бывает: все скрипты гоняются в общем скриптовом фреймворке, на девел-версии которого есть возможность сказать скрипту: «Запускайся теперь из моей рабочей директории, а не из общей». При этом любые ошибки или истечение тайм-аута возвращают скрипт обратно на общий поток, а система проследит за тем, чтобы все воркеры были только нужной версии.
Другая проблема — множественные A/B тесты. У нас их в каждый момент времени проходят буквально десятки. Раньше нужно было либо создавать десяток пользователей, чтобы захватить все варианты тестов, либо хакать код, чтобы намеренно пихать своих пользователей в интересующие тебя в данный момент варианты. А теперь мы используем общую систему UserSplit [11], позволяющую для каждого конкретного теста добавлять QA-настройки вида «Вот этот юзер всегда получает вот этот вариант» и всегда быть уверенным, что ты проверяешь именно то, что тебе нужно в данный момент.
Что такое «шот» в нашем понимании? Фактически это ветка задачи (плюс текущий мастер) в продакшен-окружении. С технической точки зрения он представляет собой директорию с нужной версией кода на одной из наших машин в стейджинговом кластере и строчку в конфиге NGINX, которая направляет в эту папку http-запросы вида habr-1.shot [12]. Таким образом шот можно указывать в качестве сервера для любых клиентов — как для веба, так и для мобильных. Создавать шоты для конкретной задачи могут все инженеры с помощью ссылки в JIRA.
Предназначен он в первую очередь для проверки работоспособности задачи в реальном окружении (вместо очень похожего, но все-таки «синтетического» девела), но также и для решения дополнительных задач, таких как генерация и проверка переводов (для того чтобы переводчики работали с новыми лексемами до попадания задачи на стейджинг и не задерживали релиз остальных задач). Также существует возможность пометить шот как external — и тогда он будет доступен не только из нашей рабочей сети (или по VPN), но и из интернета. Это позволяет нам предоставить возможность тестировать задачу нашим партнерам, например, при подключении нового платежного метода.
Главное изменение, которое произошло за последние годы —это автоматический запуск тестов в шоте сразу же после его генерации (шот гораздо более стабильное окружение, чем девел, поэтому результаты тестов здесь всегда намного релевантнее и реже дают ложные результаты). AIDA запускает здесь два вида тестов: Selenium-тесты и cUrl-тесты [13]. Результаты их прогонов постятся в задачу и отправляются лично ответственному за задачу тестировщику.
А что делать, если измененный или добавленный функционал не покрыт Selenium-тестами?! В первую очередь — не паниковать. Тестами у нас покрывается только устоявшийся либо критический функционал (наш проект очень быстро развивается, и покрытие тестами каждой экспериментальной фичи сильно бы замедлило этот процесс), а задачи на написание новых тестов ставятся уже после релиза задачи на продакшен.
А если тест есть и упал? У этого может быть две возможные причины. В первом случае в задаче есть ошибка: программист не молодец и должен задачу чинить, а тесты сделали свою работу. Во втором случае функционал работает исправно, но его логика (или даже просто верстка) изменилась и тест более не соответствует текущему состоянию системы. Нужно чинить тест.
Раньше этим у нас занималась отдельная группа QA-инженеров, ответственная за автоматизацию. Они умели делать это хорошо и быстро, но все равно каждый релиз ломал какое-то количество тестов (иногда огромное), и ребята тратили гораздо больше времени на поддержание системы, чем на ее развитие. В результате мы решили изменить подход к этому делу: провели ряд семинаров и лекций, чтобы каждый QA-инженер имел хотя бы базовые навыки для написания Selenium-тестов (а заодно и модифицировали наши библиотеки так, чтобы писать тесты стало удобнее и проще). Теперь, если в задаче тестировщика начинает падать тест, он сам же чинит его в ветке задачи. Если же случай очень сложный и требующий серьезных изменений, то все-таки отдает задачу знающим людям.
Итак, задача прошла свои три круга ада этапа тестирования и готова к релизу! В дело вновь вступает AIDA. Она собирает все готовые задачи (задача проверена на всех этапах, необходимые переводы выполнены, тикет в JIRA в правильном статусе), «мержит» их в общую ветку (решает простые конфликты самостоятельно, в сложных случаях просит помощи разработчиков), помечает ее как текущий билд, раскладывает новую версию кода на стейджинг-сервера и инициирует запуск автотестов.
Вот здесь уже проходят ВСЕ наши тесты. При изменении стейджинг-ветки запускаются смоук-тесты и полные наборы наших системных, интеграционных и юнит-тестов. Каждая ошибка в них передается ответственным за релиз людям.
Затем тестировщик проверяет задачу на стейджинге. Главным образом здесь нужно проверять совместимость задачи с остальными, уехавшими на стейджинг (их у нас в каждом билде порядка двадцати).
О нет, что-то все-таки сломалось! Надо как можно скорее разобраться, какой тикет в этом виноват! Этому поможет наша простая, но мощная система Selenium manager. Она позволяет просмотреть результаты прогонов тестов в шоте каждой задачи, находящейся на стейджинге, и запустить не прогонявшиеся тесты (по умолчанию при создании шота запускается не полный сьют). Таким образом часто можно обнаружить тикет-виновник… Но далеко не всегда. Тогда приходится рыться в логах и искать виновный код самостоятельно: все-таки не все еще можно оптимизировать.
И вот мы нашли этот проблемный тикет. Если все совсем плохо и решение проблемы требует продолжительного времени, мы откатываем тикет со стейджинга, пересобираем билд и продолжаем спокойно работать, пока невезучий разработчик чинит произошедшее. Но если же для исправления ошибки достаточно просто поменять один символ в одной строчке?
Раньше разработчики фиксили такие проблемы прямыми коммитами в билдовую ветку. Это достаточно быстро и удобно, но это настоящий кошмар с точки зрения QA. Проверить такой «приложенный к ранке лист подорожника» достаточно сложно, а еще сложнее — найти все такие фиксы и обнаружить виновника, если он вызвал новую ошибку в другом месте. Долго жить так было нельзя, и наши релиз-инженеры написали собственный интерфейс патчей.
Он позволяет приложить Git-патч к текущему билду с описанием решаемой проблемы, отмеченным именем автора и возможностью предварительного ревью со стороны другого разработчика или тестирования со стороны QA. Каждый патч привязывается к той или иной задаче, и при откате задачи из билда все привязанные к ней патчи также автоматически будут откачены.
Кажется, все всё проверили. Кажется, можно ехать на продакшен. Точно ли? Раньше ответственному за релиз инженеру приходилось самостоятельно выяснять, все ли в порядке: смотреть результаты прогонов тестов, узнавать, действительно ли все упавшие Selenium-тесты починены, все ли задачи проверены, все ли патчи протестированы и применены… Огромное количество работы и очень большая ответственность. Поэтому мы собрали такой простенький интерфейс, позволяющий каждому ответственному за тот или иной компонент (или блок тестов) поставить галочку «у меня все хорошо», и как только вся табличка зеленеет — можно ехать.
Итак, мы справились! Можно праздновать, разливать шампанское и танцевать на столе… На самом деле нет. Скорее всего, впереди еще несколько часов рабочего времени. И вполне вероятно — еще один релиз. Но даже и это не главное: контроль качества задачи не завершается в момент ее отправки пользователям!
Обязательно нужно проверить, что под давлением продакшен-окружения и сотен тысяч (или миллионов!) пользователей задача ведет себя именно так, как ожидалось. Большие и сложные проекты мы изначально выкладываем только на часть аудитории (например, только в рамках определенной страны) для того, чтобы оценить работоспособность и стрессоустойчивость системы в боевых условиях. Оценкой результатов таких экспериментов с разных сторон занимаются все участники процесса: и разработчики, и тестировщики, и менеджеры. И даже после того, как такой «эксперимент» был признан успешным и новая фича разъехалась на всех пользователей, даже несмотря на работу полноценного отдела мониторинга, всегда полезно и самим внимательно поглядеть на состояние системы после релиза: все-таки живые пользователи могут нагенерировать больше кейсов, чем может придумать
Всегда есть куда стремиться и развиваться. 4 года назад я пришел в Badoo и был в восторге от того, как здесь все было классно устроено. Я активно участвовал в развитии процессов и уже через год выступал на конференциях, рассказывая, что стало ЕЩЕ лучше. Прошло три года — и я не представляю, как мы жили без QaApi, без таких классных авто-тестов и других прекрасных и удобных штук. Посидите как-нибудь в свободное время и пофантазируйте, что бы вы хотели изменить или усовершенствовать в своих собственных процессах? Дайте волю воображению, придумайте самые невероятные фичи и поделитесь ими с товарищами. Очень может быть, что-то из этого страшно нужно всем окружающим, а реализация будет далеко не такая фантастичная, как вам может показаться. И тогда вы все (а в конечном счете и ваши пользователи) станете немного счастливее.
Кудинов Илья, Sr. QA Engineer
Автор: Badoo
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/testirovanie/221470
Ссылки в тексте:
[1] ошибок: https://habrahabr.ru/company/badoo/blog/301764/
[2] опыта: https://habrahabr.ru/company/badoo/blog/316050/
[3] GitPHP: https://habrahabr.ru/company/badoo/blog/200946/
[4] многопоточную «пускалку»: https://habrahabr.ru/company/badoo/blog/181488/
[5] облако: https://vimeo.com/94397936
[6] PHP7: https://habrahabr.ru/company/badoo/blog/279047/
[7] SoftMocks: https://habrahabr.ru/company/badoo/blog/279617/
[8] AIDA: https://habrahabr.ru/company/badoo/blog/169417/
[9] QaApi: https://habrahabr.ru/company/badoo/blog/264497/
[10] qaapi.example.com/userRegister: http://qaapi.example.com/userRegister
[11] UserSplit: https://habrahabr.ru/company/badoo/blog/278089/
[12] habr-1.shot: https://habr-1.shot
[13] cUrl-тесты: https://habrahabr.ru/company/badoo/blog/316874/
[14] мозг: http://www.braintools.ru
[15] Источник: https://habrahabr.ru/post/317700/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.