Компания
650,01
рейтинг
16 сентября 2014 в 16:08

Разработка → Continuous Delivery в Яндексе. Как разогнать свой цикл разработки, используя только Open Source решения

Перед тестированием всегда стояли и стоят две задачи – помочь команде поддерживать высокий уровень качества разработки и делать это, не задерживая весь процесс. И это справедливо не только для наших проектов в Яндексе, где мы работаем над очень большим количеством сервисов. Часто основная задача и вовсе формулируется как увеличение скорости тестирования при сохранении должного уровня качества. Скорость процесса разработки, приверженность ценностям частых и быстрых релизов – это основополагающие факторы для успеха любого продукта. У команды больше возможностей маневра, команда быстрее находит и исправляет ошибки, быстрее получает фидбек. Как же ускоряться, не теряя качества, как достичь дзена непрерывной доставки изменений?



Сегодня мы покажем, что Continuous Delivery — это просто и весело! А пользу от него можно получить, встроив его даже частично. Мы в тестировании Яндекса уже несколько лет используем подобный подход для наших библиотек с открытым исходным кодом — Allure Framework или Yandex QATools. Процесс прост, значительно масштабируем и может применяться как для огромных команд из одного человека, так и для маленьких командочек из десятков человек. А самое главное — весь инструментарий доступен в Open Source!

Кстати, до 30 сентября можно подать заявку и поступить в нашу Школу автоматизации процессов разработки в Питере. Обучение в ней бесплатное и будет состоять не только из курса лекций — обязательным этапом станет командная работа над учебным проектом.

А теперь вернёмся к теме. Представьте картину: уютное рабочее место, вы пишете код, добавляете юнит-тесты и отправляете изменения в систему контроля версий, а через пару часов они «выезжают» на боевые сервера. И все при этом работает.

Кажется, что такой процесс характерен либо для метода разработки «хлобысь, хлобысь и в продакшен» (убрав часть про юнит-тесты), либо для рекламного ролика компании, специализирующейся на инновациях при разработке ПО. При этом под ним обязательно нужна бегущая строка, аналогичная подписи под каскадёрскими трюками: «Опасно, не пытайтесь повторить дома!».

Как это было раньше


История одного разработчика. Где-то слышал задачу о бэкапах: «Сколько грузовиков нужно, чтобы администратор начал делать резервные копии?». Юмор черный, поэтому решение жду в комментариях. Здесь речь идет о процессе разработки, но суть не меняется. Разработчик отправляет любое изменение в основную ветку и, посчитав, что пора собрать пакет для тестирования и выкладки, останавливается на стабильном, по его мнению, состоянии кода, обновляя ветку, из которой собираются пакеты. Теперь возникает вопрос: «Что содержится в новом пакете после очередной сборки?». Любой ответ на этот вопрос может быть неправильным. Ведь разработчик уверен, что меняет код только он, поэтому смотреть в историю изменений не нужно. Бывало, буквально чудом, находили при тестировании аномалии, которые могли серьёзно осложнить жизнь пользователям наших сервисов. Аномалиями оказывались несогласованные изменения, попавшие в ветку либо от разработчика из другого проекта, решившего исправить баг, либо собранные «за компанию» и просто забытые. Сложности ожидали и тех, кто решил бы влиться в процесс разработки. В какой ветке ведется разработка? В какой ветке стабильная версия? Как вообще собирать пакет?

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

История нескольких разработчиков. Эта история отличается только тем, что в список ежедневной рутины каждому разработчику в команде добавляется слияние своих изменений с изменениями коллег. А еще ведь все друг другу доверяют и никто не смотрит на эти самые изменения коллег — они же знают, что пишут! Все бы и рады смотреть, что происходит с проектом, тем более когда коллега уходит в отпуск, все равно приходится разбираться, но где это делать? В среде разработки негде оставить комментарий. Лично сказать не всегда удобно, особенно если разработка ведется в разных офисах. Да и изменения уже в проекте — так просто не переделать в случае ошибок.

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

Бросаться разрушать вредные, но несущественные мифы, о которых никто не слышал и от которых никто не страдал, — непродуктивно. Поэтому, испытав первые трудности с доставкой изменений до конечных потребителей, текущую схему разработки пришлось менять.

Инструментарий


Для полного веселья потребуется: GitHub Flow как непосредственный процесс, CI сервер. Немного, правда? Наши библиотеки живут на GitHub, поэтому я буду пользоваться его терминологией, давая комментарии по ходу. Весь этот процесс вполне возможен почти на любых комбинациях CI-серверов и популярных площадках для IT-проектов, вроде GitLab, Bitbucket. Ключевое только одно: потребуется клей, называемый семейством расширений Pull Request Builders.

Соль за 5 секунд


Форк, коммит, пуш, реквест, билд, ревью, мерж, релиз.

Соль в три этапа


Все эти смешные слова я дальше употреблять не буду. Хоть и очень тянет! Тот, кто их знает и регулярно использует, скорее всего, давно внедрил подобный процесс. Эти короткие непонятные словечки так же легко выучить, как и реализовать следующие основные этапы в рамках задачи на легкое построение процесса:
  1. разработчик делает изменение;
  2. изменение смотрят другие;
  3. изменение попадает в основную ветку системы контроля версий.

Разработчик делает изменение


Точка входа — основной репозиторий, мастер-ветка. Один из главных бонусов подхода — всегда известно, где находится стабильный рабочий код, который видел не только разработчик. Прямое изменение этой ветки запрещено. Даже если очень хочется.

На этом этапе потребуется только GitHub или аналог. Первое, что нужно сделать, — продублировать текущую мастер-ветку основного репозитория в свой личный репозиторий. Тут разработчик волен строить процесс кодирования так, как ему нравится. Это его личный репозиторий, и здесь он полновластный хозяин. Конечная цель проста — набор изменений, базирующийся на мастер-ветке основного репозитория, в любой ветке личного.
На этом этапе появляестя и самая большая сложность — приучить себя писать unit-тесты на свои изменения. Самое интересное, что сложность не в том, чтобы написать эти тесты, а именно приучить себя их делать. Но если выработать такую привычку, она окупит почти любые трудозатраты на само написание тестов. Начните с малого: покрывайте позитивные сценарии. Их легко продумать, легко реализовать в тестах. Привыкнув не бояться за поломку заявленной функциональности, легко добавить негативные сценарии. Это избавит от страха непоправимо сломаться в неожиданных местах. Изменения готовы к демонстрации?

Изменения смотрят другие


По набору возможных печенек и вариантов реализации это самый технологичный этап. Этап не просто так называется «смотрят другие» — без слова «разработчики». Автоматика!

Для начала разработчику нужно запустить процесс — предложить свои изменения к слиянию в основную ветку проекта. Думаю, не нужно говорить о том, что телепаты обычно в отъезде, поэтому сообщения к каждому изменению должны четко отражать их суть. Особенно сильно это ощущается, когда сам возвращаешься после перерыва к работе над проектом и обнаруживаешь чужие изменения. Хорошо, если понятно, что произошло по заголовкам в истории GIT. Ведь после отпуска не очень-то хочется, разглядывая разницу, переваривать тонны изменений, чтобы внести маленькое исправление. В проектах с открытым исходным кодом это более чем важно — здесь за вашей историей следят уже сотни человек!



Тут в дело и вступает CI-сервер. Мы используем два: TeamCity & Jenkins. Какой точно использовать, мы так до конца и не определились. Зависит в основном от предпочтений настраивающего новую задачу на сборку. Для того чтобы сборка началась, как только в основной репозиторий приехало предложение на слияние, потребуется тот самый клей — одно из расширений семейства «Pull Request Builders».

Например, для Jenkins + GitHub это GitHub PRBP.
Для Jenkins + Bitbucket это Bitbucket PRBP.
Для Teamcity + Github это TeamCity.GitHub.

CI-сервер заботливо соберет предложенное изменение, прогонит тесты и обязательно сообщит о проблемах в самом предложении на слияние:



Прямо здесь же стоит настроить и статический анализ кода. Сейчас можно автоматически находить огромное количество ошибок в коде! Например, при помощи SonarQube. Он сможет измерить покрытие тестами и предупредить, если оно вдруг упадет. Получение обратной связи занимает минуты! Исправить ошибки можно в той же самой ветке, из которой было предложение:



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

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

Изменения попадают в основную ветку системы контроля версий


Как только изменения попали в основную ветку, наступает время интеграционного тестирования. Здесь удобнее всего поставить на караул задачу на сборку тестовых пакетов. Мы в наших библиотеках в этот момент обновляем SNAPSHOT версию в Maven репозитории. Тут уже гоняются тяжелые интеграционные тесты, проверяющие взаимодействие со сторонними компонентами, запускаются браузерные тесты, где это требуется. На этом этапе вполне реально отдать пакеты в ручное тестирование.

Чем приятен и удобен весь этот процесс? Он очень гибок. Все эти действия легко разнести на несколько каскадов. Например, делать сначала запрос на слияние в нестабильную ветку, в ней проводить все тяжелые действия по тестированию, а после них — отправлять запрос на слияние в основную ветку, в рамках которого собирать пакет на отправку на боевые сервера. И принимать запрос на слияние только после успешной выкладки. Либо наоборот — всё-всё тестирование проводить в рамках одного запроса, работая и пересобирая пакеты прямо на ходу, отправляя в основную ветку уже готовые к выкладке изменения. Это зависит от конкретной ситуации и укоренившихся привычек команды.


Как только в основной ветке накопилось достаточное количество изменений, которыми все участники довольны в нужной степени, приходит время релиза. Обычно это еще одна задача на сборку с ручным вызовом. В GitHub, например, для этого используют команду для HuBot. Очень удобно помечать в этот момент головное изменение тегом. Это позволит в любой момент при желании получить возможность собрать нужную версию, не вспоминая номер изменения.



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

Я тоже так хочу!


Для того чтобы организовать подобный процесс даже не нужно иметь собственный CI-сервер. Для маленьких проектов очень удобно использовать www.cloudbees.com/jenkins, который даст полноценный Jenkins-сервер с ограничением на количество сборок. Начать собирать предложения на слияние на GitHub вполне реально используя buildhive.cloudbees.com — у него нет лимитов. Либо travis-ci.org, для которого нужно в корень проекта положить небольшой конфигурационный файлик.

Если же у вас под рукой свой сервер, настроить на нем Jenkins или TeamCity — дело получаса. Настройки по умолчанию в этих серверах перекрывают 80% базовых потребностей, и нужно просто добавить нужные расширения.

А настроив полную цепочку на маленьком проекте однажды — масштабировать решение на соседние проекты даже больших размеров возможно за пару часов с абсолютного нуля.

Мы научим!


Если вам интересно заниматься подобными вещами, интересно строить автоматически масштабируемые системы, облегчающие разработку, сборку, а главное, тестирование, если интересно повышать качество продуктов, которыми пользуются от мала до велика, добро пожаловать к нам в Школу автоматизации процессов разработки!
Автор: @Lanwen
Яндекс
рейтинг 650,01

Комментарии (25)

  • 0
    Хорошая идея с версией релиза!
  • +3
    Почему бы не проводить такие проекты (я о школе) удаленно? Собрать группы студентов, организовать вебинары, дать им задания.
    • +8
      Мы заинтересованы в том, чтобы получить максимальный эффект от этой школы. Такое возможно только при очном обучении. Личное общение всегда останется незаменимым инструментом. Тем же кто хочет повысить свои навыки тестирования, но не сможет присутствовать лично, курс можно будет увидеть в онлайне.
      • 0
        Будет опубликовано на хабре?
        • +5
          Да, мы расскажем, когда их выложим. Пока во время школы будем готовить видео.
  • 0
    Зачем манипуляторы поднимают стеклянный колпак (третий робот), а затем опускают его обратно?
    • +1
      Это оптическая иллюзия — робот и колпак пересеклись на одной зрительной линии
      • 0
        Да, вы правы, я не обратил внимания на дальний край колпака.
        Тогда зачем манипуляторы снимают стеклянный колпак (третий робот), а затем опускают его обратно? :)
        • +3
          Полируют. Последние два вон какие блестящие :) Готовят к выпуску.
          • +1
            Достойный ответ. И правда, блестящие :)
  • +2
    1. Мерж А и мерж Б по отдельности не имеют ошибок. Но совместно создают ошибку. На каком этапе вы это отлавливаете?

    2. Мерж А попал в основную ветку и провалился на тестах. Затем пришел мерж Б, которые прошел тесты. Как теперь мержу Б попасть в продакшен? Он должен будет ждать, пока не исправят мерж А?

    3. Зачем тестировать в основной ветке? Почему не тестировать в ветке самого мержа?
    • 0
      я возможно промахнулся кнопочкой ответить :) Ответ ниже
  • 0
    1. Предполагается что на функциональность из мержа А и мержа Б есть юнит тесты. Предположим что они приехали одновременно пулл-реквестами. На каждом прошли юнит тесты, они оба успешны. Мержим то что в А. Этот мерж меняет поведение компонента С, на который ссылается мерж Б. Мерж Б требует ребейза на мастер, ибо содержит старые версии тестов на компонент С. После ребейза тесты перезапускаются и падают, сообщая о проблеме. Т.е. о проблеме узнаем перед тем как привели в актуальное к мержу состояние мержа Б.

    2. Мерж А не может попасть в основную ветку провалив тесты. Если это произошло случайно, необходимо откатить коммит, поломавший тесты, ибо это прямое нарушение условия «в основную ветку попадают только изменения, прошедшие юнит тесты и ревью». После чего мерж Б попадает в продакшен ничего не зная о мерже А.

    3. Тут зависит от схемы выкатки релизов и мягкости условия о стабильности кода в основной ветке. Например, если у нас каждый пулл-реквест — это фактически версия, тут тестировать нужно в ветке мержа безусловно. Тогда в основную ветку попадут уже готовые к выкладке изменения. Т.е. приехало в мастер — выкладываем в продакшен.

    Если мы собираем готовую версию только набрав нужное количество изменений, здесь можно тестировать конечный релиз и в основной ветке. Например в нашем Allure Framework в мастере всегда гарантированно просмотренный и прошедший юнит тесты код. Но мы допускаем, что перед выпуском версии можем собрать несколько фич разом в одной сборке и скопом прокликать вручную и тяжелыми тестами все, после чего делать релиз. Это более лояльно ко времени участников — всем не надо проверять регрессию на каждом пулреквесте, мы считаем что в основном ничего не сломали (ибо есть юнит и интеграционные тесты). А какие то глубокие промахи в дизайне или юзабилити можно устранить либо в следующей версии, либо оттянув текущую.

  • 0
    1. Мерж Б требует ребейза на мастер, ибо содержит старые версии тестов на компонент С.

    Что значит требует? Кто/что, в какой момент и как определяет, что мерж Б требует ребейза?

    2.
    Мерж А не может попасть в основную ветку провалив тесты.


    Как это не может? Цитирую из статьи:

    Как только изменения попали в основную ветку, наступает время интеграционного тестирования.


    Т.е. сначала мерж попадает, а потом тесты. И вот они, допустим, провалились.

    3. Это более лояльно ко времени участников — всем не надо проверять регрессию на каждом пулреквесте


    Не понял. Как так не надо? Именно, что надо — ничей мерж не должен ломать мастера. И это как-раз лояльно к ко времени участников — не надо ждать исправлений от сломавшего мастер.
    • 0
      1. Это определяет гитхаб (или геррит, или что используется для организации гитхаб-флоу). У него кнопка пропадает yadi.sk/i/BZ99RBkgbX4fD. Если же ребейз автоматический (т.е. без конфликтов) то гитхаб рассылает пуши об обновлении пулл-реквестов, после которых и происходит пересборка.

      2. Цитирую из статьи чуть раньше:
      CI-сервер заботливо соберет предложенное изменение, прогонит тесты и обязательно сообщит о проблемах в самом предложении на слияние. <...> После успешной сборки — время для осмотра кода живым человеком

      Если билд провалился, над кнопкой рисуется красный крест. Не заметить его сложно. Предполагается что увидев это человек не будет нажимать на кнопку мержа, если он в здравом уме.

      Стадия интеграционного тестирования, может мигрировать из основной ветки в ветку с мержем. Интеграционным называется тестирование, проверяющее интеграцию с другими компонентами. Т.е. Возможна ситуация когда интеграционные тесты не проходят, но при этом код в основной ветке полностью рабочий. В этой ситуации нужно смотреть по проекту. Если это какой то важный компонент, то стадию интеграционных тестов нужно делать ДО мержа (вопрос п.3). Если интеграция с другими компонентами — проблемы других компонентов, то тут можно сэкономить, не запуская тестов на интеграцию на каждый мерж, а только перед непосредственно релизом, чтобы уведомить других что у них что-то может сломаться.

      3. Мастер не ломается. Поломка на интеграционном тестировании не считается поломкой мастера. Ибо код в мастере рабочий и успешно проходит юнит тесты. Тут вопрос процесса — если считать интеграцию достаточно важной составляющей рабочего продукта и рабочего мастера — тогда конечно.

      • 0
        Промазал. Коммент ниже.
  • 0
    1. Если же ребейз автоматический (т.е. без конфликтов) то гитхаб рассылает пуши об обновлении пулл-реквестов, после которых и происходит пересборка.


    Не сталкивался с таким поведением. Куда он рассылает пуши и что это вообще? Если не трудно.

    2. Если билд провалился, над кнопкой рисуется красный крест.


    Это понятно. Но допустим этот этап прошел успешно, дальше вы нажали кнопку, мерж А ушел в основную вету, поехали интеграционные тесты в основной ветке. И вот тут вылез баг. Как теперь мержу Б попасть в продакшен?".

    3. Мастер не ломается. Поломка на интеграционном тестировании не считается поломкой мастера.


    Не понял. Что вы тогда называете интеграционным тестированием? Что с чем интегрируется и что из этого имеет право не пройти тесты, но при этом мастер будет считаться рабочим?
    • 0
      Как любит повторять создатель дженкинса «Polling must die!»
      У гитхаба очень хороший механизм хуков. Это специальные нотификации, которые представляют из себя POST запрос по заранее заданному урлу. Гитхабу просто скармливается список урлов, которые он должен дернуть в случае наступления определенных событий. Дальше CI сервер принимая пуш на свой урл смотрит к какой сборке этот пуш относится.
      Картинки:
      yadi.sk/i/gT5p6weDbX8T8
      Если зайти в конкретный хук, можно увидеть когда были отправлены пуши
      yadi.sk/i/f0gHaGSpbX8Z5

      2. Тесты делятся обычно на юнит-тесты (те которые непосредственно код тестируют). Интеграционные (они тестируют компонент целиком в вакууме, заглушив все внешние компоненты заглушками и проверяя, что наш компонент взаимодействует с остальными корректно — вызывает нужные методы, рассылает нужные уведомления). Функциональные тесты (они проверяют бизнес логику). End-to-end тесты (те которые смотрят как ведет себя вся цепочка взаимосвязанных компонентов). Тесты на отображение UI (обычно это скриншотные тесты, тесты на то что все элементы действительно видны итд). Замыкают пирамиду на самом верху тесты ручные, часть из которых замещается автоматическими тестами, имитирующими конечного пользователя — WebDriver тесты.

      Собственно никаких противоречий где все тесты запускать нет — это вопрос удобства и требований к качеству на каждом из этапов. Просто чем выше пирамида, тем более долгие и тяжелые тесты. Поэтому, например, вебдрайверные тесты почти нереально запускать на каждый коммит, если тестировать ими серьезные сценарии.
      Интеграционные тесты исходя из этого могут быть частью сборки, а могут быть частью релиза. Если делать их частью сборки, то они проходят во время каждого билда и если они здесь сломаются, эффект от их поломки будет аналогичным поломке юнит-тестов. Если делать их частью релиза, то тогда они запускаются только на стадии, когда мы хотим сделать релиз. Тогда все что хотелось мержить в рамках этого релиза можно мержить при условии успеха юнит-тестов и успеха ревью. Далее релиз фиксится до победного БЕЗ добавления новых фич. Новые фичи ждут в своих мерж ветках момента, когда будет выпущен релиз и на зарелиженный мастер можно будет заребейзиться.

      На примере:
      У нас есть модуль авторизации. Мы покрыли юнит тестами что при заполнении логина, пароля у нас заполняется модель пользователь, мы покрыли юнит тестами что у нас нет исключений при невалидных значениях данных, и что мы по готовности отправляем сериализованную модель в нужном формате куда скажут.

      Интеграционные тесты. Здесь мы ставим заглушку на бд, и проверяем что до бд действительно доходит то же самое, что мы сериализовали в модуле авторизации. Так же, мы проверяем, что если мы запросили авторизацию с верными данными, нам вернулся код ответа 200 ОК. И если неверные, то 403 FORBIDDEN. То что мы умеем отсылать коды ответа мы проверяем в юнит тестах. Аналогично ставим заглушку на модуль который пишет журнал, и смотрим, что если мы запросили доступ, то до журнала долетела запись.

      Функциональные тесты. Мы поднимаем бд, заполняем ее пользователями для проверки. Авторизуемся пользователем из бд и не из бд, и смотрим что нам пришли нужные коды ответа, а в журнале действительно сохранилась запись.

      ну и дальше — больше участников просто и больше слоев.

  • 0
    Правильно ли я понял? Последовательность такая:

    — Созданы мержи А и Б.
    — Гитлаб для каждого мержа отправил уведомление в CI.
    — CI для каждого мержа прогнал тесты. Допустим, тесты прошли успешно. Об успешности тестов CI отписался в комментарии к мержу.
    — Далее мерж А был принят в мастер (кто-то нажал кнопку).
    — Гитлаб отправляет уведомление в CI о том, что мастер обновился.
    — CI теперь должен сделать ребейз всех мержей, которые уже были ранее протестированы, но еще не были приняты в мастер (в нашем случае это мерж Б). Сделать ребейз и снова програть тесты.

    Да? Если да, тогда вопрос — а не получится так, что между принятием мержа А и ребейзом мержа Б кто-то успеет принять мерж Б в мастер? Как определить, что мерж Б нельзя принимать, ибо он еще должен быть отребейзен?
    • 0
      Последовательность верная. По крайней мере в гитхабе и геррите так работает.

      В гитхабе во время сборки есть индикатор над кнопкой, показывающий что идет сборка.

      Если прям секунда в секунду взять и смержить все что было, не успев среагировать на изменения интерфейса — тут честно признаюсь, не знаю что будет. Ну кажется выходом будет только проглядывать ленту изменений перед слиянием. Мне сложно представить процесс разработки большого продукта в котором часто что-то мержат, при этом делают это абсолютно молча и игнорируя чужие пул-реквесты. Тут кажется проблема уже не на стороне системы сборки а на стороне менеджмента и коммуникации между разработчиками. Поэтому решать нужно именно ее, а не думать как разруливать бесконтрольные ломающие друг друга мержи.
  • 0
    1.
    Например, для Jenkins + GitHub это GitHub PRBP.
    Для Jenkins + Bitbucket это Bitbucket PRBP.
    Для Teamcity + Github это TeamCity.GitHub.

    А для Teamcity + Bitbucket существует?

    2.
    В чем особенности работы с Bitbucket по сравнению с GitHub'ом?

    3.
    Тесты делятся обычно на юнит-тесты...

    Давно искал такого описания типов тестов, спасибо. Где можно подробнее почитать?
    • +1
      1. Путем несложного поиска нашел: github.com/ArcBees/teamcity-plugins/wiki/Configuring-Bitbucket-Pull-Requests-Plugin
      2. Битбакет поддерживает не только git + у него есть приватные репозитории. Наверное это может наложить какие то особенности. + Разное api. Это может повлиять на функциональность конечной связки. Но в целом, особых отличий быть не должно. Речь идет только о каких-то дополнительных плюшечках.
      3. Для того чтобы хорошо ориентироваться в автоматизации, тестировании и разработке обязательно стоит почитать эту литературу:
      1) «Sun Certified Programmer for Java Platform, SE6» Richard F. Raposa
      Пособие по подготовке к соответствующему сертификационному экзамену. Рассматриваются все основы языка. Скорее всего, есть только в английском варианте.
      2) «Effective Java» Bloch Joshua
      Продвинутый уровень, помогает глубоко понять идеологию java. Есть русский перевод, «Java. Эффективное программирование»
      3) «Refactoring: Improving the Design of Existing Code» Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts
      Продвинутый уровень, не только по java. Есть русский перевод, «Рефакторинг. Улучшение существующего кода»
      4) Сэм Канер, Джек Фолк, Енг Кек Нгуен. Тестирование программного обеспечения. Фундаментальные концепции менеджмента бизнес-приложений
      5) Роман Савин, teстирование dот com
      6) Гленфорд Дж. Майерс «Искусство тестирования программного обеспечения»
      7) Шаблоны проектирования xUnit

  • 0
    Видео всех лекций доступно здесь: habrahabr.ru/company/yandex/blog/245869/

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка