Как сделать чтобы порушенные билды не мешали коллегам?

Есть репозиторий, в него куча народу делает коммиты. Проекты билдятся, запускаются юнит тесты, и если билд не поломался, а юнит тесты прошли успешно, есть ещё беда — база данных может после них прийти в негодность и в следующий раз поломаются правильные юнит-тесты. Тогда пишем скрипт, который на чистой машине с нуля создаёт тестовую среду, билдит, затем запускает тесты, если всё удалось, делаем коммит, иначе не делаем и шлём мейл виновнику. Всё вроде хорошо, ан нет, что вся это конструкция работает долго, как быть если пришёл второй коммит пока не отработал первый — можно создать вторую VM и отрабатывать второй коммит там. Но как быть если сами по себе коммиты работают нормально, а когда вместе, то ломают билд? Есть какая-то правильная теория и правильные инструменты, позволяющие всем вместе работать над проектом без риска обрушить билды?
  • Вопрос задан
  • 2660 просмотров
Пригласить эксперта
Ответы на вопрос 7
eugenius_nsk
@eugenius_nsk
Навскидку сразу видно несколько проблем.

Во-первых, никакие тесты не должны изменять после себя базу. Если это интеграционные или приёмочные тесты, то их, например, можно проводить в транзакции, откатываемой после завершения каждого теста (кроме того, можно использовать in-memory DB — это заодно и ускорит выполнение тестов). А если это юнит-тесты, то они вообще не должны лезть в базу — надо переписывать код таким образом, чтобы юнит-тестирование не требовало обращений к БД (это, кстати, как правило и общее качество кода улучшает и делает код легче переиспользуемым).

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

Кроме того, если все билды выполняются на одной машине, то их надо выполнять последовательно, а не параллельно — это уменьшает накладные расходы и общее время сборок/тестирования. А вот если вы выполняете сборки на разных машинах (например, TeamCity это умеет) — тогда да, можно запускать и параллельно, чтобы вычислительный ресурс не простаивал :-)
Ответ написан
Комментировать
Mithgol
@Mithgol
По-хорошему в таких обстоятельствах следовало бы перейти к распределённой системе контроля версий (то есть к DVCS). Ну, например, перейти на Git. И тогда у каждого разработчика на машине будет его собственный репозиторий, а не только один главный (центральный, основной) репозиторий для залития туда всех правок. Причём и этого мало: надо непременно, непременно дополнить всё это также распределённою же системою тестирования, то есть устроить дело так, чтобы каждый разработчик у себя на машине мог лично проверить, работоспособен ли код из его собственного репозитория — и только тогда заливать его в основной (центральный) репозиторий. Причём опять же заливать следует не сразу, а сперва скачать из центрального репозитория свежие правки, применить их (устранив при необходимости конфликты слияния, если центральные правки меняют тот же кусок кода, что и собственные правки разработчика), затем вдругорядь оттестировать на работоспособность — и только тогда заливать.
Ответ написан
donnerjack13589
@donnerjack13589
io.js core developer
Я думаю, что запускать две VM для разных коммитов и merge'ить оба является некорректным решением. Почему бы не запускать build'ы по очереди?
Ответ написан
Wott
@Wott
Правильная теория — разделять работу разных людей/команд.

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

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

А то что тестирование делается долго повод организовать работу так что бы оно делалось в нерабочее время автоматом. Если девелопер просто хочет проверить свой билд, то стоит тесты разделить на быстрые и полные. Собственно с тестами такая же история как и с изменениями — они тоже могут меняться, добавляться для ветки, пока вместе с соответствующими изменениями не упадут в мастер.
Ответ написан
Комментировать
eaa
@eaa
Хм… если коммит связан с мелким фиксом, то нем никакого смысла гонять абсолютно все тесты — а в большом проекте это может занять несколько суток. Во-вторых, большие фичи коммитятся не так часто, так что случай с пересечением коммитов явно из ряда вон выходящий — в конце концов второй коммит может либо подождать, пока протестируется первая фича, либо коммитить обе и тестировать сразу обе. В-третьих, любое изменение в более-менее большом проекте тестируется самим разработчиком до коммита, разрабатывается в отдельном бранче и в обязательном порядке проходит ревью кода, так что «случайно» что-то сломать очень и очень сложно — все такие случайности отвалятся еще до коммита. Вывод один и очень простой: «семь раз отмерь — потом отрежь».

Да, еще слышал такую практику — кто ломает билд — ставит пиццу на весь офис. Говорят, сильно помогает получше всяких юнит-тестов ;)
Ответ написан
@relgames
Java Developer
Я на своих проектах сделал так, что запуск тестирования каждый раз происходит на новой JVM и с Embedded DB. Вместо JBoss стал использовать Embedded JBoss, который запускается внутри этой JVM, для Web слоя использую Jetty. Все коннекты к внешним системам заменил на стабы, работающие строго по спецификации этих систем, некоторые стабы подключил напрямую, не используя сокеты и JMS.

Самое важное было при запуске менять открываемые JBoss-ом и Jetty порты, чтобы можно было запускать тестирование нескольких проектов одновременно.

В итоге, примерно 550 тестов на самом «тяжелом» проекте отрабатывают на нашем тестовом сервере где-то за 25-30 минут (машинка не очень шустрая).

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы