В июле мы вместе с ведущими IT-Kompot и релиз-инженерами Badoo Владиславом Черновым и Олегом Оямяэ записали выпуск подкаста «Процесс разработки и выкатка релизов в Badoo. Автоматическое тестирование. Девелоперское окружение».
Так как прошлый подкаст вызвал интерес у слушателей и читателей, то этот подкаст мы тоже превратили в статью.
О чем говорили:
Процесс разработки и выкатки релизов в компании Badoo. Используемые инструменты.
- GIT Workflow. Каждая задача в отдельной ветке;
- Использование JIRA, TeamCity и AIDA;
- Формирование релиза и выкатка двух релизов в день. Проблемы и их решения (откат, патчи и т.д.).
Автоматическое тестирование. Рецепт быстрого прогона большого количества тестов.
- Что мы используем;
- Как гоняем тесты;
- Code Coverage;
- Пускалка. 18000 тестов за 3,5 минуты.
Девелоперское окружение в команде, разрабатывающей сложную распределенную систему
И рекомендации от ребят: полезные книги, статьи и т.д.
Антон Копылов: Всем привет, вы слушаете 48 выпуск подкаста «IT-компот», и с вами его ведущие Антон Копылов.
Антон Сергеев: И Антон Сергеев, привет.
Антон Копылов: Сегодня у нас в гостях бравые ребята ― релиз-инженеры компании Badoo Олег Оямяэ и Владислав Чернов. Ребята, привет!
Владислав Чернов: Привет.
Олег Оямяэ: Привет.
Антон Копылов: У нас получается цикл подкастов с компанией Badoo. Сегодня мы решили более подробно поговорить про область, которая является если не гордостью компании Badoo, то уж точно очень важным достижением и явным успехом. Это то, что компания делает успешно выкатку новых релизов, используя при этом полностью автоматизированные средства. Плюс в компании очень интересно сделан и настроен процесс тестирования. Он позволяет эффективно проводить большое количество тестов. Все, кто слушал прошлый выпуск подкаста, уже знают про 2 релиза в день ― про это говорил Алексей Рыбак.
Ну что, давайте начнём. Влад и Олег, я вам предлагаю рассказать коротко о себе и о том, чем вы занимаетесь в Badoo.
Владислав Чернов: Здравствуйте ещё раз. Мы с Олегом занимаемся в Badoo конфигурационным управлением и релиз-инжинирингом. Если говорить про себя, то я почти всю свою трудовую карьеру занимаюсь именно релиз-инжинирингом: начинал как обычный релиз-инженер, делал очень много руками, мы выкатывали простые релизы, а потом я ушёл в автоматизацию и всё больше и больше автоматизировал, накручивая этот процесс. Сейчас занимаюсь автоматизацией всего бизнес-процесса разработки и тестирования в Badoo.
Антон Копылов: Понятно, круто. А Олег ― твой коллега и тебе в этом помогает, правильно?
Олег Оямяэ: На самом деле у меня немного другая история. Я был разработчиком и тимлидом в других компаниях, а в Badoo решил попробовать себя в новой для меня сфере ― в релиз-инжиниринге. Но я занимаюсь больше программированием, а не автоматизацией. Давайте я расскажу немного о том, как всё было устроено в Badoo с начала и до наших дней.
Антон Копылов: Да, давайте поговорим про историю вашего процесса разработки, как вы всё это начали делать, ведь до такого состояния, как сейчас, удалось дойти явно не сразу. Наверное, было много всяческих преград и задач, которые приходилось решать. Расскажите, как это всё начиналось, почему получилось так, как сейчас, и как вы к этому пришли.
Олег Оямяэ: Довольно длительное время в Badoo в качестве системы контроля версий использовался SVN. То есть большую часть существования Badoo использовался SVN, и он даже до сих пор в некоторых частях используется. (Примечание: в далеких-далеких годах, конечно, был CVS).
Антон Копылов: Сейчас некоторые слушатели, наверное, начинают «писать кипятком»: как же так, subversion! Но, насколько я знаю, SVN, он больше свойственен проектам типа enterprise всякого. У вас был с ним большой опыт работы ещё начиная с Mamba, то есть это исторически так сложилось, правильно?
Олег Оямяэ: Переход на Git начался года два с половиной назад: в это время как раз пошёл какой-то бум и все начали переходить на него. Но в Badoo это был запланированный процесс, как часть внедрения тестирования в компании.
Антон Сергеев: А вы не рассматривали Mercurial как альтернативу Git?
Владислав Чернов: Насколько я знаю, мы не рассматривали альтернативу Mercurial, потому что на тот период количество плагинов, ПО для управления репозиториями и так далее больше было на Git. Плюс сообщество уже тогда сформировалось, а на Mercurial только начинало. Для меня, например, особый плюс ― это то, что Git использует любые языки, а с Mercurial все сложней.(Примечание от руководителя тестирования Ильи Агеева: Mercurial мы пробовали вводить много лет назад, но он у нас не прижился и мы вернулись обратно на SVN).
Антон Сергеев: Угу, хорошо.
Олег Оямяэ: Вот так вот. Соответственно, два с половиной года назад начался процесс по внедрению контроля качества. Был создан отдел, который растёт и развивается до сих пор. Как раз в тот период было разработано новое workflow, в котором каждая задача делалась в отдельной ветке, но по-прежнему собиралось всё руками, не было ни автоматизации, ни, по большому счёту, ничего. Выкладка происходила, можно сказать, совсем руками. Была утилита, которую написали очень-очень давно, посредством неё всё выкладывалось, и никакого мониторинга не было. Со временем было много написано вокруг этой утилиты ― dashboards и прочие вещи, она стала своего рода ядром. Это если вкратце.
Антон Сергеев: А процесс выкладывания и тестирования, он у вас был вместе собран или это были разные процессы?
Олег Оямяэ: Раньше это были не совсем связанные между собой процессы. Сейчас же это полноценная непрерывная интеграция, когда после каждого коммита прогоняются тесты, и это непосредственно влияет на выкладку и на staging. Эти два процесса сейчас связаны между собой и влияют друг на друга.
Антон Копылов: Кстати, ребят, хотел спросить ваше мнение. Понятно, что многие проекты при старте чаще всего используют только систему контроля версий и, допустим, какие-то хуки, чтобы это контролировать. Обычно никто сразу не ставит мощные средства для continuous integration, для деплоя. Как считаете, что может являться переходной точкой, насколько проект должен разрастись, чтобы стало понятно, что невозможно дальше обходиться без нормального continuous integration и без тестов?
Олег Оямяэ: Лично моё мнение, что на любом проекте с самого начала нужно задумываться об интеграции этих вещей, и тем более о написании тестов. И тесты, наверно, даже первичней. Особенно если проект пишется с нуля ― в этой ситуации о покрытии тестами стоит задумываться на самых ранних этапах развития.
Антон Копылов: То есть если бы вы сейчас делали Badoo заново, то вы сразу взяли бы такую систему и самый первый коммит попал бы уже через continuous integration и прошел бы все тесты?
Олег Оямяэ: Ну я бы ― да.
Владислав Чернов: Я бы сказал немножко по-другому. Если мы говорим о «попсовом» слове start-up, то понятно, что никто не будет делать такую сложную систему, потому что неизвестно, взлетит ли start-up, а ресурсы на тесты тратятся немаленькие, плюс у нас всегда есть ограниченные сроки, за которые мы должны выдать продукт на рынок. Соответственно, говорить об автоматическом тестировании с начала проекта, наверное, не нужно. Но говорить и думать про автоматические сборки и, возможно, какое-то «версионирование» и автоматическое развертывание надо с самого начала, потому что это не займёт очень много времени у команды проекта и это небольшие ресурсы по сравнению с теми же автоматическими тестами.
Антон Копылов: Понятно. А давайте вы ещё вкратце нам расскажите по поводу того, как у вас проходят 2 релиза в день, про несколько этапов тестирования, n-ое количество тестов и как это работает. Про откаты, патчи, хотфиксы.
Владислав Чернов: Давайте я сначала немножко вернусь к истории: 2 релиза в день ― это действительно так, у нас уезжает порядка 50-60 задач в день. Всем, наверно, будет интересно узнать, почему именно 2 релиза. Всё очень просто. Понятно, что сначала был один релиз в неделю или один релиз в несколько дней, потом был релиз каждый день, а потом стало два релиза в день. Почему два?
Мы перешли в какой-то момент на flow, где каждая задача делается в отдельной ветке, и, соответственно, когда мы формируем релиз, мы сливаем эти задачи в релизную ветку, проверяем повторно каждую из задач и плюс мы проверяем смерженность кода (интеграционное тестирование). Когда это от 10 до 30-40 задач максимум ― это сделать достаточно легко. Когда вам нужно разгребать 100 задач в этом релизе, то это уже сделать сильно сложнее. И поэтому мы деплоим два раза в день, мы можем деплоить и чаще, но в этом нет большого смысла. Почему каждая задача в отдельной ветке, наверно, тоже ясно. У нас есть несколько этапов тестирования, их где-то около 5. Каждая задача в отдельной ветке, потому что мы её можем откатить и проверить. Получается, что у нас есть код с production плюс эта задачка. И мы её проверяем на нескольких этапах тестирования. Первый этап стандартный ― это code review, и смотрится только эта задача. Сделанная задача проверяется на девелоперском окружении. Девелоперское окружение ― это наша мини-серверная с виртуальными машинами, с базами и так далее. На ней можно проверять такие вещи, которые нельзя проверить в production. Задачи там тестируются, потом мы создаём мини-стейджинг для каждой задачи, он называется shot, база используется из production, и мы проверяем задачу ещё раз. Потом задача уезжает в релиз и проверяется на смерженность кода уже в релизной ветке, не ломает ли она другие задачи. И так далее и так далее. Там задача проверяется в четвёртый раз. И есть опциональные тестирования на post-production, когда мы тестируем эту задачу по какому-то запросу от product-менеджера, либо это очень важная задача и тестировщики повторно её проверяют на production, но это опциональные вещи.
Антон Копылов: А как у вас происходит code review? Его делают какие-то специальные люди, либо разработчики случайным образом делают review кода других разработчиков?
Владислав Чернов: В каждом отделе всё проходит по-разному. Когда задача попадает на review, выбирается разработчик или группа разработчиков. В одних группах review делают руководители команд по компонентам. В других ― задачи просто ротируются внутри группы. Это зависит и от численности отдела, и от опыта людей, и от традиций.
Антон Копылов: Ребята, давайте я задам вопросы, которые прислали слушатели. Например, Станислав прислал нам много вопросов всяких-разных. Я их разбил на несколько групп. Например, он спрашивает, кто принимает конечное решение о выкате релиза ― бездушная машина или какой-то аналог Сергея Дидыка.
Олег Оямяэ: Нет, у нас нету Сергея Дидыка, он есть в другой компании (примечание: речь идет о компании Бегун). У нас релиз идёт два раза в день в определённое время утром и вечером и, соответственно, мы собираем из задач релиз до этого времени, потом автомерж останавливается и мы начинаем тестировать эти задачи. Когда задачи протестированы и приходит момент выкатки релиза, релиз-инженер принимает решение и мы уезжаем на production.
Антон Копылов: Чем выкатываете? И как закатываете назад, если не выкатилось? На какой промежуток времени можете откатиться назад, если что?
Владислав Чернов: Для выкатки у нас есть своя утилита для деплоя, она написана нашим разработчиком Юрием Насретдиновым. Если есть желание узнать про это подробнее, то у Юрия есть несколько докладов и статья об этом. Утилита очень быстро выкатывает тысячу серверов, буквально за 2-3 минуты. Это наша система деплоя, и мы её постоянно улучшаем.
(Примечание: откат ― это такая же выкатка, только номер версии другой. Таким образом и выкатиться, и откатиться мы можем за несколько минут. Откатиться даже быстрее, т.к. предыдущая версия на серверах остается. Нужно просто перекинуть линк, а это несколько ssh-команд для переключения и сброса кэша).
Антон Копылов: А она есть где-нибудь на GitHub, её можно обычным людям пощупать?
Владислав Чернов: Нет, её нет, а почему ― это, наверное, вопрос к Юрию Насретдинову.
Антон Копылов: Понятно, будем надеяться, что выложите. Было бы интересно пощупать, конечно.
Владислав Чернов: Да.
Антон Сергеев: А у меня такой ещё вопрос, вы говорите, что у вас есть стадия тестирования, когда на стейджинге с production-базой проверяется код. А каким образом вы данные переносите с production в стейджинг? Если обнаруживается проблема, то что вы с этим делаете?
Олег Оямяэ: А что вы имеете в виду под этой проблемой?
Антон Сергеев: Могу ли я проверить на стейджинге, например, не на ста миллионах пользователях, а на одном миллионе? Или вы переносите целиком всю базу и на полном объёме проверяете этот код?
Олег Оямяэ: Нет, там используется не копия, а полноценный настоящий production.
Антон Сергеев: Ааа.
Олег Оямяэ: И только код с некоторыми новыми изменениями, а база используется именно от production.
Антон Сергеев: Угу. А не страшно на стейджинге коннектиться к production-базе?
Олег Оямяэ: Нет, потому что тестирование происходит на тестовых пользователях, то есть даже если там что-то случится, это никак не «зааффектит» и не потревожит настоящих пользователей (плюс до этого задача тестируется дважды).
Антон Копылов: Кстати, у нас похожий подход используется в компании и мы пытаемся от него уйти, но при этом думаем, нужно ли от него уходить. Тут главное здравый смысл: если действительно ничего страшного не делать, коллекции, например, не дропать, то, наверно, всё будет хорошо.
А ещё Стас спрашивает, используете ли вы выкатывание на часть кластера. Пользователи туда прибиты или это может быть любая часть кластера? Я так понимаю, что речь идет о том, можно ли выкатить на часть кластера, потестить и потом выкатить для всех.
Владислав Чернов: Я могу так ответить на этот вопрос: мы можем выкатить на любую машину и на любой кластер. Мы используем порядка 10 кластеров. И можем выкатить этот код с помощью утилиты на любую из частей кластера. По поводу интереса того, что куда-то выкатить и потестить, то мы в основном выкатываем для тестирования новой фичи и нам хочется посмотреть на результаты. Мы выкатываем отдельную страну, а не какой-то набор машин, потому что это гораздо удобнее.
Антон Копылов: Понятно. А как у вас происходит откат? Допустим, у вас какая-то фича попала в релизную ветку и что-то пошло не так в процессе тестирования на стейджинге. Например, вы обнаруживаете, что есть какая-то серьёзная проблема и желательно её пока что откатить. То есть расскажите, как вы работаете с системой контроля версий (Git), используете ли вы git rebase или git revert. И если да, то расскажите, как.
Владислав Чернов: Мы используем git rebase, мы именно его используем, потому что git revert нас не устраивает, так как мы разрабатываем каждую задачу в отдельной ветке. Если мы откатываем с помощью revert после сливания ветки релиза и ветки мастера, то разработчику придётся делать revert на revert, поэтому мы используем git rebase. Мы моментально откатываемся, соответственно, собираем новую сборку и выкладываемся на стейджинг.
Антон Копылов: А у вас не было проблем с git rebase? Насколько я знаю, штука эта довольно капризная, её нужно уметь правильно использовать. Какой у вас тут рецепт?
Владислав Чернов: На самом деле она не такая уж и капризная и рецепт очень прост: мы вмерживаем в релизную ветку другие ветки, и у нас дерево релизной ветки очень простое, и откатить задачу очень просто, так как это смерженный коммит. И мы понимаем, что git rebase ― это полностью ручная операция. Но у нас есть алгоритм и небольшой скрипт, который выполняет это в автоматическом, ну почти в автоматическом режиме.
Антон Копылов: Мы уже знаем, что вы используете Git, но помимо этого вы ещё используете такой замечательный инструмент от компании JetBrains, как TeamCity ― это continuous integration server, а ещё у вас это всё заинтегрировано с баг-трекером JIRA, я так понимаю ― и постановка задач, и автоматические смены статусов. Как у вас всё это появлялось и интегрировалось, и как вы с этим работаете?
Олег Оямяэ: Да, как уже было сказано, мы используем Git, а также JIRA и TeamCity. TeamCity мы используем для прогона тестов и выкладки кода на стейджинг при успешном прогоне. На самом деле, flow в JIRA у нас сильно проработан и структурирован, и заинтегрированы все компоненты системы JIRA, Git и TeamCity. У нас очень большой workflow который мы регулярно оптимизируем, чтоб было удобно и разработчикам, и тестировщикам, и менеджерам продукта.
Антон Копылов: Кстати, на последней конференции DevConf был доклад про проблемы в архитектуре, и спикер говорил, что JIRA ни в коем случае не нужно использовать, потому что там нельзя раздавать права разным пользователям на уровне просмотра задач, чтобы, допустим, разработчики не видели какую-то там дополнительную метаинфу, которая нужна проект-менеджеру, а проект-менеджер не видел каких-то деталей, которые могут быть полезны только разработчикам. Насколько это вообще, по-вашему, критично и с какими вы сталкивались проблемами с JIRA? Были какие-то действительно серьёзные вещи, которые вы как раз допилили?
Владислав Чернов: Эта проблема с проект-менеджером и с разработчиком, она какого-то очень закрытого плана, мы на самом деле все дружим и у нас нет скрытой информации, и нет такой проблемы по филдам, например, ― скрывать их или нет. По поводу того, использовать JIRA как баг-трекер или нет ― это каждый выбирает сам, но это как минимум самая распространённая система в мире, именно как баг-трекер. В чём-то она нас устраивает, в чём-то ― нет. Там, где она нас не устраивает, мы автоматизируем работу с ней. На самом деле, у нас сложный workflow, но в JIRA два уровня вложенности таска и сабтаска, и из-за этого мы получаем больше плюсов, чем минусов, т.к. не можем усложнить процесс.
Антон Копылов: Угу. А Вы используете confluence? Если слушатели наши не знают, я просто сейчас скажу, что confluence ― это wiki, где можно хранить документацию и не только.
Владислав Чернов: Да, конечно, мы используем его. И я вот боюсь ошибиться, но насколько я знаю, мы даже пользуемся GreenHopper. Но мы не используем FishEye для просмотра кода, потому что это очень громоздкий инструмент, и мы для review кода используем GitPHP, который, опять же, сами допиливали, и он достаточно быстр по сравнению с тем же FishEye, который индексирует огромное количество наших веток несколько суток.
Антон Копылов: А какое у вас впечатление от работы с TeamCity? Пользовались ли чем-то ещё, пробовали ли Jenkins, например?
Владислав Чернов: Да, я работал со многими серверами непрерывной интеграции: и с Jenkins, и с TeamCity, и с Bamboo. Но TeamCity нас устраивает в большей степени, чем остальные сервера непрерывной интеграции, в данный момент представленные на рынке.
Антон Копылов: А можете поподробнее рассказать, с чем это связано? С вашим текущим процессом, с выкаткой релизов или там есть какие-то особенности, которые другие разработчики тоже могли бы учесть. Допустим, сейчас нас слушает разработчик и думает, что ему выбрать. Есть ли какие-то важные факторы, по которым стоит выбрать TeamCity?
Владислав Чернов: Одно из преимуществ TeamCity в том, что его бесплатного функционала достаточно для того, чтобы его могли использовать маленькие компании. С другой стороны, у него есть платные функции, он поддерживает платный support и сделан качественно. Все говорят, что Jenkins хорош тем, что для него очень много плагинов. Это действительно так, но получается, что если вы рассчитываете на какой-то плагин, а потом выходит новая версия Jenkins, бывает, что плагин не переписывается, и вы сталкиваетесь с проблемами, и вам нужно опять всё перестраивать.
TeamCity нас подкупил как минимум тем, что он достаточно прост в использовании и удобен не только релиз-инженерам, но и тестировщикам, и девелоперам. Плюс на тот момент у них выходили определённые фичи, которые нам отлично подходили. Это, например, ловля ветки по маске, а у нас огромное количество веток, и мы не перестраиваем билды. Потом эти фичи были добавлены в другие серверы непрерывной интеграции, но это уже было потом. Ну и, конечно, support нас отлично поддерживает и помогает, они дорабатывают продукт и некоторые вещи доделывают под нас.
Антон Сергеев: Я ещё хотел добавить, что в TeamCity одна из фич, которая мне кажется killer-фичей, ― это наследование конфигурации. Можно сделать шаблон конфигурации и потом от него уже создавать какие-то клоны. Это сильно упрощает процесс добавления подпроектов в систему.
Владислав Чернов: Да. Это как если вы, допустим, используете один репозиторий и у вас нет кастомных конфигураций, и какие-то вещи вы можете настроить как шаблон и либо передать параметры, либо ещё что-то. Это тоже интересная особенность.
Антон Сергеев: Это как раз то, чего нет у конкурентов ― наследование конфигурации, такая вот фишка TeamCity.
Антон Копылов: А у меня ещё вопрос по поводу Git. Все знают или по крайней мере слышали про так называемый git-flow. Это такой стандартный подход к использованию Git. Данный подход был разработан достаточно давно, и это удачная модель бранчинга. Ваше flow основано на этом стандартном подходе, где используются feature branch, release branch, hot-fix branch, master, developer branch, или у вас есть свои фишечки, какие-то хорошие рецепты ― как лучше создавать ветки, как лучше сливать ветки ― что про это можете рассказать?
Владислав Чернов: Да, конечно. На самом деле мы далеки от git-flow. У нас всё просто: есть мастер, в котором содержится копия кода на production, туда никто не имеет право пушить, туда могут применять патчи, у нас есть специальный для этого инструмент, он называется Deploy Dashboard. Релиз-инженер смотрит этот патч: если всё хорошо, он его применяет в полуавтоматическом режиме в веб-интерфейсе, и, соответственно, код разложится на production и что-то там пофиксится. Это бывает достаточно редко, но бывает, конечно. И у нас есть релизная ветка, которая создаётся два раза в день полностью в автоматическом режиме, плюс есть ветки задач. В ветке задачи нумеруются по тикетам JIRA: номер тикета и какое-то описание ветки. И вот тикет создается, эта ветка вместе с тикетом идёт по flow, она разрабатывается, идёт на review, проверяется в несколько этапов тестирования, потом автоматически мержится в релизную ветку, и здесь включается сервер непрерывной интеграции, который собирает этот билд. И хотя у нас PHP-код, он у нас действительно собирается. Например, гоняются переводы, которые автоматически генерятся более чем на 40 языков и, соответственно, выкатываются на стейджинг и к окружению, и всё это делается в автоматическом режиме. Релиз заканчивается, он мержится в мастер и создаётся автоматически новый релиз.
Антон Сергеев: У меня вопрос возник: а нумерацию вы какую-нибудь ведёте? Если у вас 2 релиза в день, то у вас, наверное, очень много релизов уже набралось, или не так быстро растёт этот номер?
Олег Оямяэ: Не совсем так. Да, в TeamCity есть внутренний инкремент, но он больше используется для работы непосредственно с TeamCity, а так сами имена релизов носят более «человекопонятный» формат, то есть там присутствует дата, время и проект, потому что мы выкладываем не только для web ― с недавних пор и для iOS, и для других проектов. Так что у нас нет такой проблемы, как, например, «релиз 365», и никто не понимает, что это вообще такое и откуда.
Антон Копылов: Да, бывает такая проблема. Я сталкивался с ситуацией, когда есть у тебя задача, допустим, в Redmine, и ты пишешь, что фича такая-то, таск такой-то. Потом смотришь в релиз, а там куча фич. Ты говоришь: «Да что ж такое-то, какая из них моя?» И приходится в браузер лезть, чтобы там смотреть.
Я считаю, что несмотря на то, что каждый из инструментов, который вы используете, будь то JIRA, TeamCity или Git, сам по себе хорош, но лучше всего и эффективней всего они себя показывают, как мы видим, на вашем примере ― в интеграции. И вот для этого вы используете такой инструмент, как AIDA, правильно? Расскажите, как вы это делаете, как к этому пришли и какие профиты получаете?
Олег Оямяэ: Да, мы используем AIDA. Это такой виртуальный пользователь, от лица которого происходят все автоматические действия, какие-то скрипты запускаются, рассылаются нотификации в Jabber, в почту, обновляется информация в dashboard, то есть весь процесс автоматизирован, вся информация доступна как в TeamCity, так и в JIRA. Также у нас есть определенный формат commit message, когда мы просматриваем Git log, тоже всё видно и понятно. Также в JIRA присутствуют ссылки на GitPHP в конкретной задаче: всегда можно посмотреть как полный diff, так и все коммиты по отдельности. Так что да, наверно, использование этих трёх инструментов вместе действительно удобно и оправдано.
Антон Копылов: А насколько сложно начать работать с AIDA, или это очень простой инструмент, не какой-то там rocket science?
Олег Оямяэ: Скажем так: там есть простые части, но есть и достаточно витиеватые.
Антон Копылов: Какие у вас были самые серьёзные проблемы, с которыми вы столкнулись, используя AIDA и при интеграции с TeamCity, JIRA, Git?
Олег Оямяэ: Ну смотрите, на самом деле AIDA во многих случаях использует API к JIRA, TeamCity, с Git она работает как обычный пользователь. Первая часть, с которой мы столкнулись, это, конечно же, API. Оно меняется от версии к версии, и нельзя сказать, что оно всегда стабильно. И это была первая ситуация, когда мы столкнулись с трудностями. По поводу реализации AIDA, вопрос в том, как грамотно настроить бизнес-процесс: например, в какой момент создать ветку релиза, в какой момент запустить automerge и так далее. Правильно выстроить нотификации, потому что люди должны понимать как идёт этот процесс, и если мы что-то упустим, то AIDA будет работать без нас, и это будет неконтролируемый процесс. Выстраивание этого процесса ― это и есть самая большая сложность.
Антон Копылов: Получается, это всё отлаживается, пишется, прогоняется, смотрится и так далее до тех пор, пока более-менее не войдёт в нормальный рабочий ритм, правильно?
Олег Оямяэ: Да. У нас есть специальное окружение, в котором мы пишем и тестируем AIDA, так что в большинстве случаев какие-то доработки и изменения проходят гладко и ничего не ломается. В этом плане всё хорошо.
Антон Копылов: Ясно. А есть планы на будущее, может быть, какие-то интересные технологии в плане выкатки, деплоя, автоматизации, на которые вы смотрите, либо которые вы видите сейчас на рынке? Или вы пока более чем довольны вашими инструментами и не хотели бы что-либо менять?
Олег Оямяэ: Да, пока нас всё устраивает, мы дорабатываем AIDA и всё хорошо.
Антон Копылов: Супер. Предлагаю тогда перейти к следующей большой теме. Давайте поговорим про тестирование и про то, как вы делаете автоматическое тестирование, что для этого используете, как это всё происходит и каких показателей вам удалось добиться?
Владислав Чернов: Да, мы используем автоматическое тестирование. Если начинать с самого начала, то стоит сказать, что unit-тесты у нас пишут разработчики. На данном этапе времени задача не принимается в релиз, если она не покрыта unit-тестами. Соответственно, мы используем Selenium для PHP-кода, считаем code coverage, это достаточно стандартно. У нас в какой-то момент возникла достаточно большая проблема из-за двух релизов в день: это ограниченное время, это буквально несколько часов на тестирование и сейчас, соответственно, у нас нет последовательного процесса, у нас всё идёт параллельно. Например, идёт push в релизную ветку, автоматически запускается сборка, автоматически запускаются unit-тесты и selenium-тесты ― параллельно, и, может быть, опционально отдельные какие-то тесты, которые очень важны. И мы столкнулись с такой проблемой, что у нас было порядка 18 000 тестов (примечание: сейчас 20000), и они проходили очень большое количество времени.
Наш замечательный коллега Илья Кудинов написал утилиту, которую мы называем «Пускалка», которая делит эти тесты на 11 потоков, при том она их полностью формирует по времени, так чтобы каждый поток проходил за равные промежутки времени, и сейчас у нас тесты гоняются где-то порядка 3,5 минут ― это 18 тысяч юнитов. И тесты гоняются не только на релизной ветке ― они гоняются также после того, как разработчик завершил свою задачу в ветке. Также в автоматическом режиме. Там существует отчёт, который пишется в JIRA, и разработчик либо тестировщик сразу же может посмотреть результат прогона этих тестов: что упало, что не упало и так далее.
Антон Копылов: Ага. А по поводу Selenium, есть опять же от Станислава вопрос, большая ли ферма под Selenium?
Владислав Чернов: Я могу ошибаться, но насколько я знаю, ферма достаточно большая. Это связано с тем, что мы поддерживаем довольно большое количество браузеров и мы только недавно отказались от Explorer 6, то есть мы тестируем почти на всём: это и Chrome, и Firefox, и Explorer. И сама ферма достаточно большая. Мы также «распараллеливаем» тесты, пускаем их по параллели по причине того, что они проходят довольно продолжительное количество времени. Мы пробуем использовать браузеры и движки без GUI, но я не могу похвастаться и сказать, что это очень успешно проходит.
Антон Копылов: Ага. Кстати, мне вспоминается знаете что: я был на Форуме Технологий Mail.ru, и там был доклад или от Яндекса, или от Mail.ru (честное слово, забыл) о том как они используют Selenium. И там был смысл примерно в том, что они сначала запускали для каждого браузера отдельную ноду ― я так понимаю, что это какая-то виртуальная машина типа Xen'а, и это всё получается довольно «ресурсозатратно» и не очень хорошо, и Selenium бил по рукам, что нельзя на одной это ноде запускать тесты одновременно для разных браузеров, потому что будет ломаться, будут глюки, в общем, будут проблемы. И они полезли в сорцы, что-то там подпилили, поняли какие-то особенности того же Explorer’а, когда ему, не знаю, фокус принудительно вернуть, что-нибудь ещё сделать, чтобы все тесты параллельно не падали. И они об этом рассказывали и говорили, что это вообще мегакруто, что мы смогли так и заставили так работать всю эту систему, что всё стало быстро проходить. Вы подобными вещами вообще баловались, сталкивались с этим? И как вы смотрите на подробного рода «костыли»?
Владислав Чернов: Я не знаю, что на самом деле происходит в браузерах, мы все-таки не пишем selenium-тесты и не знаем таких подробностей. Но на мой взгляд, есть браузеры, которые обновляются довольно часто, и тогда эти костыли надо переносить от одного браузера к другому как минимум. По поводу упавших тестов: selenium-тесты ― это такие тесты, которые всё равно падают, и самый распространённый способ это устранить ― это прогнать эти тесты повторно и посмотреть, упадут они или нет. По поводу того, кто что делает, например, по поводу отдельных виртуальных машин, мы это не используем, и для каждого отдельного браузера принимать свою машину слишком ресурсозатратно. Но, что интересно, Google, например, гоняет selenium-тесты на своем дата-центре.
Антон Копылов: Ничего себе.
Владислав Чернов: Да, при этом машины ― это production-площадки, комовская площадка. Он берёт те же машины, которые используют пользователи, и гоняет там selenium-тесты, так что ресурсы у всех разные. Мы стараемся всё-таки менее ресурснозатратно всё делать.
Антон Копылов: У нас еще остались вопросы от слушателей. Какие типы тестов вами пишутся?
Владислав Чернов: Смотрите, у нас как минимум есть unit-тесты и, понятное дело, функциональные тесты. То есть мы лезем в базы, мы смотрим там базы на devel. У нас есть Selenium, который работает на devel, на обоих площадках. У нас два дата-центра, и инфраструктура devel полностью повторяет инфраструктуру площадки. У нас здесь две площадки, и репликация баз на devel такая же, как на площадках. То есть всё, что есть на production, есть сейчас и в девелоперском окружении. Но мы гоняем selenium-тесты и на девелоперской площадке, и на стейджинг, и на какие-то критические моменты на production. Для PHP это, наверное, и всё.
Антон Копылов: Ещё тогда такой вопрос: unit-тесты совсем unit? Без БД? Если да, то как тестируется связка хитрых SQL-запросов с парой джоинов и тем, что это обрабатывает?
Олег Оямяэ: Мы стараемся писать unit-тесты как unit-тесты, а хитрые запросы ― для этого есть функциональные тесты, которые как раз для этого и нужны. Unit должен быть Unit’ом и проверять только одну конкретную часть.
Антон Копылов: Есть ещё вопрос от Стаса (он задал очень много вопросов, и я не могу удержаться ― надо же ответить человеку, раз ему интересно). Используете ли вы A/B-тестирование и как тестируете производительность?
Олег Оямяэ: Да, мы используем A/B-тесты. Правда это делается средствами другого отдела, но в Badoo используется A/B-тестирование, чтобы понять, какой вариант дизайна текста или, например, кнопки, лучше и приятней пользователю, чтобы сервис становился ещё более удобным и понятным. Для этого тоже есть специальные инструменты автоматизации.
Антон Копылов: А производительность как тестируете? Я так понимаю, что здесь имеется в виду производительность не самих тестов, потому что вы сказали, что у вас 18 тысяч тестов проходят за 3,5 минуты, да?
Олег Оямяэ: Да. Всё верно.
Антон Копылов: А производительность, не знаю, допустим, response на production, на какой-то конкретный запрос.
Олег Оямяэ: Не уверен, правильно ли я понял вопрос. Но у нас есть отдел мониторинга, который непрерывно ―24 часа в сутки 7 дней в неделю и так далее ― мониторит состояние всей системы, всех, абсолютно всех частей, а также время ответа страниц, насколько быстро отдаётся статика. Если что-то пошло не так, тут же эскалируется проблема ответственному лицу и проблема в кратчайший срок локализуется и исправляется.
Антон Копылов: Давайте ещё поговорим по поводу code coverage: какие у вас требования есть к покрытию кода, как вы с этим работаете, насколько покрываете. Как я понял, самое главное это то, что код без покрытия не попадает в релиз. Но а дальше как вы это мониторите, насколько много стараетесь писать тестов?
Олег Оямяэ: Тестами должен покрываться весь новый функционал, то есть когда разработчик отдаёт какую-то задачу в тестирование, все методы, новые или изменённые, он обязан покрыть unit-тестами. Соответственно, потом задача уходит в Q&A, Q&A пишет selenium-тесты, функциональные тесты и затем считается coverage раз в сутки, и дальше руководители отделов, тестировщики и все заинтересованные лица в специальном веб-интерфейсе могут посмотреть, у какой группы насколько хорошее покрытие, и сделать соответствующие выводы, поставить какие-то задачи на дописывание unit-тестов, или отдел тестирования поставит задачу на дописывание Selenium’а. Всё это непрерывный процесс улучшения кода и покрытия.
Антон Копылов: А давайте ещё тогда поговорим про вашу «пускалку», о которой вы только вскользь упомянули. Мне интересно подробнее узнать, насколько всё-таки у вас улучшилась производительность, сколько было, сколько стало, и поподробней расскажите про архитектурно-философские подходы, которые использовались при разработке «пускалки»?
Владислав Чернов: Мы там рассматривали несколько схем, даже самые простые, например, разделение какими-то suites на n-ое количество тестов и запуск их, и разные другие варианты. Они тоже все описаны, и про них можно почитать. По поводу профита и того, как это было реализовано, расскажу сейчас поподробнее. Профит мы получили, так как, если я не ошибаюсь, тесты гонялись где-то в районе 20 минут, может быть, даже больше. Но сейчас это 3,5 минуты, то есть мы получили огромный выигрыш по времени. По поводу реализации, мы разбиваем запуск на 11 потоков, при этом suites формируются так, что они берут время из определённой базы, которая сформирована на основе базы TeamCity-сервера. Мы знаем, сколько гоняется каждый тест, мы собираем эту информацию, если я не ошибаюсь, за 7 дней, берём какое-то среднее значение и, соответственно, знаем, сколько этот тест в среднем гоняется. На основе этой информации собирается эта статистика и формируется 11 одинаковых потоков и идёт запуск. Потоки получаются полностью сбалансированными, там даже выдаётся результат, сколько тесты будут идти, такой взгляд в будущее.
Антон Копылов: Ясно. А есть какие-то мысли по поводу того, как это можно ещё улучшить, куда можно двигаться дальше? Может быть, в дальнейшем вы это в open-source выложите, чтобы и другие могли попользоваться и порадоваться?
Владислав Чернов: Да, Илья Кудинов обещал, что уже в ближайшие несколько месяцев мы сможем это сделать. Просто сейчас это немножко кастомизировано под нас и, соответственно, нам нужно это оформить просто под Jenkins, например, и выложить это в open-source. Я думаю, что это будет сделано, и все смогут попробовать и поиграться с этим.
Антон Копылов: Здорово. Вы, конечно, молодцы, потому что и последнее время много рассказываете на конференциях о том, как вы вообще разрабатываете, статьи на Хабре пишете и, опять же, вот к нам в подкаст с удовольствием приходите. Это очень интересно, и думаю, что многим разработчикам интересно послушать про ваши инструменты. Потому что есть технологии, которые сейчас крупные компании и крупные игроки на рынке выкладывают, и вот они многие, честно говоря, какие-то спорные, а многие технологии даже никто и не использует, о них только говорят на конференциях. Я не буду конкретно говорить, но вот у меня есть такое мнение по поводу определённых вещей, систем, что они слишком уж кастомные и не очень интересные для комьюнити. В вашем случае, я думаю, что это совсем не так, поэтому желаю удачи в том, чтобы вы доработали и выложили эти инструменты на GitHub либо ещё куда-то. У нас есть немножко времени напоследок, давайте поговорим про девелоперское окружение. Вы говорите, что у вас есть полная копия production непосредственно в офисе, где сидят разработчики. Как вы подходите к вопросу девелоперского окружения, есть ли у каждого разработчика свой какой-то sandbox, что собой представляет эта ваша копия production, какая у вас здесь структура?
Антон Сергеев: Ну да, и используются ли какие-то средства для повтора окружения, типа Vagrant или Puppet?
Олег Оямяэ: Да. У нас в production есть два дата-центра основных, в Праге и в Майами. Соответственно, нам требуется на devel’e воссоздать также две площадки, чтобы можно было тестировать какие-то кроссплатформенные вещи. База у нас абсолютная копия, структура абсолютно такая же. Но тем не менее, вся конфигурация полностью совпадает, тем самым позволяет нам без каких-либо проблем разрабатывать код, тестировать его, все сервисы ― всё поднято, и разработчикам вполне комфортно разрабатывать.
Антон Копылов: Это единая какая-то конфигурация, то есть там Puppet или Chef используется?
Олег Оямяэ: Да, используется Puppet для production и для всего, то есть все вещи раскладываются через него, все конфиги. За счёт этого у нас все конфиги консистенты и нет никаких проблем с тем, что на одной машине один конфиг, а на другой ― другой.
Антон Копылов: Кстати, классный подход. Но вот мы, например, тоже используем Puppet, но мы создали отдельный конфиг для девелопмента. Почему? Потому что несколько отличается у нас от девелопмента среда. Например, мы MongoDB на ту же тачку, в общем-то, кладём, где у нас идёт обращение к API или к вебу, к фронтенду. И у нас они чуть-чуть отличаются, эти конфиги, но в общем мы тоже довольны, потому что мы их оперативно обновляем. Если у нас обновляется, скажем, PHP, либо что-то ещё, либо драйвер Mongo-вский, то это занимает немного времени. А вот с машинами разработчиков как у вас обстоят дела? У вас, кстати, исторически больше разработчиков на «винде», либо на «маках», либо на Linux, как у вас происходит на локальных машинах разработка и первое тестирование?
Олег Оямяэ: На самом деле разработка ведётся на DEV-серверах в большинстве случаев. Некоторые разработчики поднимают у себя локальный nginx или ещё что-то, но, наверно, для каких-то очень узкоспециализированных и маленьких задач. Но невозможно на локальной машине поднять всё окружение, и просто даже не нужно. То есть разработчики себе разрабатывают в своей домашней директории на devel’e. Соответственно, у каждого разработчика есть свой виртуальный хост, который маппится в его домашнюю директорию в специальную папку. По поводу того, каких операционных систем больше, я вот в офисе видел, по-моему, только одного разработчика на «винде», может двух, но, в основном, это «маки» и Linux, но в процентном соотношении, не знаю, мне кажется, 50 на 50.
Антон Копылов: Вот так вот, интересно. Но в вашем случае непринципиально, на чём сидит разработчик, потому что он всё равно всё делает где-то там на devel, там единственная разница будет, что у него, может быть, будут несколько другие средства, GUI для доступа к базе в зависимости от платформы. И насколько я знаю, многие нормальные разработчики сейчас всё больше к нативным инструментам прибегают. В базу из консоли заходят, поэтому тут тоже проблем никаких. Я почему ещё спросил, потому что есть практика, когда девелопментная среда поднимается, но, например, под тем же Vagrant’ом. Сначала разработчик пишет и сохраняет свой код на эту виртуалку с Vagrant’ом; там, скажем, какой-нибудь Linux-сервер крутится, а потом уже оно заливается на DEV-сервак. Но я так понял, в вашем случае этого лишнего звена нет, вы сразу разрабатываете и тестируете на devel, потом оттуда сразу собираете и на стейджинг.
Владислав Чернов: Да, это так, потому что, на самом деле наша серверная ― это как раз и есть набор виртуальных машин. И единственное место, где мы используем сейчас облачные технологии. Виртуальные серваки мы используем, но это devel-oкружение, и мы не используем виртуалки под какие-то конкретные задачи, единственное, понятно, где нам нужны виртуальные машины, определённая ось, либо ещё что-то ― это, конечно же, для тестирования и для разных браузеров, тогда мы поднимаем виртуальные машины именно для таких конкретных задач. А так нам действительно хватает нашего devel, тем более он поддерживает огромное количество функциональности, которая у нас есть на production. Это гораздо удобнее, чем поднимать виртуальную машину для какой-то конкретной задачи.
Антон Копылов: Здорово, что вы всё-таки с этим разобрались, что поддерживаете нормальный DEV, потому что, насколько я знаю, в компаниях среднего размера это постоянная головная боль, особенно то, что тестится не на той платформе, на которой это будет работать. Версии ― и то могут отличаться, и даже иногда разница небольшая в версиях, а на production из-за этого может всё поломаться, и это очень важно, потому что много времени тратится на то, чтобы понять и пофиксить. И если это происходит постоянно, то это неправильная процедура тестирования и неправильное окружение.
А давайте перед самым завершением нашего сегодняшнего диалога вы дадите какие-то рекомендации от себя, что почитать в плане книг, статей, на какие конференции можно сходить, если, вы интересуетесь тестированием, автоматизацией, тем самым деплоем либо созданием распределённых больших систем, похожими на ваши.
Владислав Чернов: Ну, как минимум подписывайтесь на наш блог на Хабре, и, может быть, мы что-то ещё там интересное для вас расскажем. У нас там много интересных статей. Если говорить не про непрерывную интеграцию, то стоит всё-таки читать Бергмана, он как минимум даёт какие-то начальные знания и основные понятия, и вот эти книжки:
- Jez Humble & David Farley «Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation»;
- Paul M. Duvall, Steve Matyas & Andrew Glover «Continuous Integration: Improving Software Quality and Reducing Risk»;
- Alan Berg, «Jenkins Continuous Integration Cookbook»
Они достаточно интересны. Если мы говорим о больших системах, то, если честно, мало кто с удовольствием рассказывает про бизнес-процессы, про конфигурационное управление, про релиз-инжиниринг, и это очень грустно.
Антон Копылов: Наверное, просто каждый проект, он уникален, есть какие-то свои фишки, свои ноу-хау, но многие компании, действительно, имея высоконагруженный проект, становятся всё более и более закрытыми. Тут можно «ВКонтакте» привести в качестве примера, потому что они очень мало инфы наружу дают, и их появление на конференциях всегда воспринимается «на ура», но тем не менее, вытянуть из них что-то очень сложно. Я, по своему опыту общения на HighLoad, могу сказать, что там очень порционно удаётся информацию о них получать. Поэтому большое спасибо вам за статьи на Хабре, они очень интересные и, в принципе, оттуда некоторые мысли и решения мной были позаимствованы для своего проекта.
Антон Сергеев: Ну вот и всё, о чём мы хотели вам рассказать сегодня, дорогие слушатели. Спасибо, что присылаете вопросы. Конечно, пока что лишь некоторые пользователи нам их шлют, но, думаю, что со временем и другие тоже будут формулировать свои вопросы и задавать их нашим гостям. Мы будем стараться давать больше времени между анонсом выпуска и до его фактической записи, для того чтобы можно было обдумать, что-то ещё спросить. Я напомню, что сегодня с вами были ведущие подкаста Антон Копылов и я, Антон Сергеев.
Антон Копылов: И наши гости из компании Badoo ― это релиз-инженеры Олег Оямяэ и Владислав Чернов. Спасибо большое, ребят.
Антон Сергеев: Да, спасибо за интересный рассказ, было очень здорово и интересно.
Олег Оямяэ: Спасибо вам за интервью.
Антон Сергеев: Слушайте наши выпуски на сайте «IT-kompot.ru», также на подкаст-терминале podfm.ru, подписывайтесь в iTunes. Удачной вам разработки и услышимся, пока.
Автор: Badoo