Це хороша практика запускати одиничні тести на гачках управління версіями?


43

З технічної точки зору можна додати кілька виштовхувальних гачків до / після, які будуть виконувати тести одиниць, перш ніж дозволити об'єднати певну комісію до віддаленої гілки за замовчуванням.

Моє запитання - чи краще зберігати одиничні тести в конвеєрному конвеєрі (таким чином, вводячи розбиті коміти на репо) або краще просто не допускати "поганих" зобов'язань.

Я розумію, що ці два варіанти мене не обмежують. Наприклад, я можу дозволити всі зобов’язання до розгалуження та тестування, перш ніж натискати на об'єднання об'єднань до репо. Але якщо вам доведеться вибирати саме ці два рішення, яке саме ви виберете і з яких саме причин?


1
пов'язані з : stackoverflow.com/questions/31681746
tkruse

Відповіді:


35

Ні, це не з двох причин:

Швидкість

Коміти повинні бути швидкими. Наприклад, комісія, яка займає 500 мс., Занадто повільна і спонукає розробників до поміркованіших зобов'язань. Зважаючи на те, що на будь-який проект, більший за Hello World, у вас будуть десятки чи сотні тестів, для їх запуску знадобиться занадто багато часу під час попередньої фіксації.

Зрозуміло, для великих проектів все гірше, коли тисячі тестів працюють протягом декількох хвилин на розподіленій архітектурі або тижнів чи місяців на одній машині.

Найгірше - це те, що ви можете зробити, щоб зробити це швидше. Невеликі проекти Python, які мають, скажімо, сотню одиничних тестів, потребують принаймні секунди, щоб запустити на середньому сервері, але часто набагато довше. Для програми C # це буде в середньому чотири-п’ять секунд через час компіляції.

З цього моменту ви можете або заплатити додаткові 10 000 доларів за кращий сервер, що скоротить час, але не на багато, або запустити тести на декількох серверах, що лише сповільнить справи.

Обоє добре платять, коли у вас є тисячі тестів (а також функціональні, системні та інтеграційні тести), що дозволяють запустити їх за лічені хвилини замість тижнів, але це не допоможе вам для малих масштабних проектів.

Натомість ви можете:

  • Заохочуйте розробників запускати тести, тісно пов’язані з кодом, який вони змінили локально, перш ніж здійснити комісію. Вони, можливо, не можуть запустити тисячі одиничних тестів, але вони можуть виконати п'ять-десять з них.

    Переконайтесь, що знайти відповідні тести та запустити їх насправді просто (та швидко). Наприклад, Visual Studio здатний виявити, на які тести можуть вплинути зміни, внесені після останнього запуску. Інші IDE / платформи / мови / рамки можуть мати подібну функціональність.

  • Тримайте зобов’язання якомога швидше. Застосування правил стилю нормально, тому що часто це єдине місце для цього, і тому, що такі перевірки часто бувають надзвичайно швидкими. Зробити статичний аналіз добре, як тільки він залишається швидким, що трапляється рідко. Запуск тестів на блоці не в порядку.

  • Запустіть одиничні тести на сервері безперервної інтеграції.

  • Переконайтеся, що розробники повідомляються автоматично, коли вони порушили збірку (або коли не вдалося виконати тести одиниць, що практично те саме, якщо ви розглядаєте компілятор як інструмент, який перевіряє деякі можливі помилки, які ви можете ввести у свій код).

    Наприклад, перехід на веб-сторінку, щоб перевірити останні збірки, не є рішенням. Вони повинні бути повідомлені автоматично . Відображення спливаючого вікна або надсилання SMS - це два приклади того, як їх можна повідомити.

  • Переконайтеся, що розробники розуміють, що зламати збірку (або провалити регресійні тести) не так, і щойно це станеться, їх головним пріоритетом є виправлення. Не має значення, чи працюють вони над першочерговою особливістю, яку їхній начальник попросив відправити на завтра: вони не виконали збірку, вони повинні її виправити.

Безпека

Сервер, на якому розміщено сховище, не повинен запускати спеціальний код, наприклад, тести одиниць, особливо з міркувань безпеки. Ці причини були вже пояснені у CI runner на тому ж сервері GitLab?

Якщо, з іншого боку, ваша ідея - запустити процес на сервері збирання з гака, який попередньо здійснює, то це сповільнить ще більше зобов'язань.


4
Я погоджуюсь, для цього потрібен сервер збирання. Ваш джерело управління призначений для управління вихідним кодом, не забезпечуючи роботу вашої програми.
Метью

4
У крайньому випадку відплата може бути необхідним інструментом сповіщення при порушенні збірки.

37
Півсекунди занадто повільно? Це крапля відра у порівнянні з тим, щоб дати остаточний погляд на те, що робиться, а потім продумати та набрати відповідний коментар.
Doval

5
@Doval: різниця полягає в тому, що, коли ви даєте один остаточний вигляд або думаєте про коментар, ви ставитесь до ініціативи , і так, ви не чекаєте. Це не час, який ви витрачаєте до введення останнього символу в IDE, і час, коли ви можете почати вводити знову після завершення фіксації, це важливо, але скільки ви чекаєте. Ось чому компілятори повинні бути швидкими; неважливо, що ви витрачаєте набагато більше часу на читання та написання коду, тому що, роблячи це, ви не чекаєте, тоді як, коли код збирається, ви спокушаєтесь перейти на іншу діяльність.
Арсеній Мурценко

10
@Thomas: мова не йде про відволікання, а про роздратування. Таким же чином, 100 мс. "має вимірний вплив" на те, як люди користуються веб-сайтом. Ту ж схему: 100 мс. це ніщо в порівнянні з часом, який ви витрачаєте на перегляд відео YouTube або запуск ПК: свідомо ви не помітите різниці між 600 мс. і 700 мс. затримка. Але несвідомо це впливає на вашу поведінку. Таким же чином, трохи повільніше вчиняє відсторонення від раннього та частого вчинення.
Арсеній Муренко

41

Дозвольте мені бути тим, хто не погодиться зі своїми колегами-відповідями.

У світі TFS це відоме як рейтингові реєстрації, і я очікую в інших місцях. Коли ви намагаєтеся зареєструватися у відділення із закритою реєстрацією, набір серверів відправляється на сервер, що гарантує, що ваші зміни будуються та визначені (прочитані: усі) одиниці тестування проходять. Якщо вони цього не роблять, він повідомляє вас, що ви погана мавпа, яка зламала збірку. Якщо вони є, зміни переходять у контроль джерела (так!).

На мій досвід, реєстрація під відкритим небом є одним з найважливіших процесів для успішного тестування одиниць - і, відповідно, якість програмного забезпечення.

Чому?

  • Оскільки заїзд, що проходить через закриті двері, змушує людей виправляти пробиті тести. Як тільки зламані тести стають тим, що люди можуть зробити, а не повинні , вони стають безвідмовними від лінивих інженерів та / або наполегливих ділових людей.
    • Чим довше ламається тест, тим важче (і дорожче) його виправити.
  • Тому що, як тільки люди повинні запускати тести, а не повинні проводити тести, запуску тестів обходять ледачі / забудькуваті інженери та / або наполегливі ділові люди.
  • Оскільки, як тільки одиничні тести впливають на ваш час, люди дійсно починають дбати про те, щоб зробити свої тестові одиничні тести. Швидкість має значення. Важливість відтворюваності. Надійність має значення. Ізоляція має значення.

І звичайно, є користь, яку ви принесли спочатку - коли ви зареєструвались на реєстрації та надійний набір тестів, кожен набір змін є "стабільним". Ви зберігаєте всі ці накладні витрати (і можливі помилки) "коли була остання хороша збірка?" - всі побудови досить хороші, щоб розвиватися проти.

Так, для складання та запуску тестів потрібен час. За моїм досвідом 5-10 хвилин для хорошого розміру програми C # та ~ 5 кб тестів. І мені це не байдуже. Так, люди повинні заїжджати часто. Але вони також повинні часто оновлювати свої завдання, або перевіряти свою електронну пошту, або отримувати каву або десятки інших «не працюючих на код» речей, які складають роботу інженера-програміста, щоб зайняти цей час. Перевірка поганого коду набагато дорожча, ніж 5-10 хвилин.


3
+1 Хочу додати, що багато проектів з відкритим кодом мають чітке розмежування між внеском і зобов'язанням. Причини цього дуже схожі на те, чому існують закриті реєстрації.
JensG

Однією з суттєвих проблем із заїздом у ворота є те, що він пригнічує спільне вирішення складних проблем. Це ще важливіше для розподілених команд.
CuriousRabbit

2
@CuriousRabbit - як ти уявляєш? Люди рідко здійснюють спільну діяльність, навіть якщо вони працюють спільно. Інакше шельфети або недієві гілки завдань спрацьовують для цього, не перешкоджаючи іншій команді.
Теластин

@ Telastyn– Shelvesets - це новий термін для мене. Я вважаю, що це варіант MS VS, який не є варіантом для великої кількості проектів. У сфері розробки мобільних додатків VS є не гравцем.
CuriousRabbit

3
@CuriousRabbit - справді? Команда, розподілена на 17 годин, піклується про те, щоб чекати 10 хвилин на вчинення зобов’язання, ніж можливість розбитий збірки, поки порушник спить? Це здається ... Менш оптимальним.
Теластин

40

Коміти повинні працювати швидко. Коли я ввожу якийсь код, я хочу, щоб він пересувався на сервер. Я не хочу чекати кілька хвилин, поки він працює безліч тестів. Я відповідаю за те, що я натискаю на сервер, і мені не потрібно, щоб хтось доглядав мене за допомогою гачок.

Однак, як тільки він потрапить на сервер, його слід проаналізувати, перевірити блок і побудувати негайно (або за короткий проміжок часу). Це попередило б мене про те, що одиничні тести порушені, або вони не складені, або я зробив безлад, показаний наявними інструментами статичного аналізу. Чим швидше це зроблено (збірка та аналіз), тим швидше мій відгук і швидше я зможу це виправити (думки не повністю витіснилися з мого мозку).

Так що ні, не ставте тести і таке, щоб робити гачки на клієнта. Якщо потрібно, покладіть їх на сервер у поштовій комісії (оскільки у вас немає сервера CI) або на сервері збирання CI та попередить мене про проблеми з кодом. Але не перешкоджайте виконанню комітету в першу чергу.

Я також повинен зазначити, що з деякими інтерпретаціями тестово керованої розробки слід перевірити одиничний тест, який пробивається першим . Це демонструє та документує помилку. Тоді пізнішою реєстрацією буде код, який фіксує тест одиниці. Попередження будь-яких перевірок до проходження одиничних тестів призведе до зменшення ефективного значення перевірки в одиничному тесті, яке не зможе задокументувати проблему.

Пов’язано: Чи слід проводити одиничні тести на відомі дефекти? і Яке значення перевірки при невдалому тесті одиниць?


2
Commits should run fast.які переваги від цього? Мені цікаво, оскільки ми зараз використовуємо контрольно-пропускні пункти. Зазвичай мої чеки - це сукупність години або близько того роботи, тому 5 хвилин чекання - це не велика справа. Насправді я виявив , що його , як правило ті часи , коли я перебуваю в поспіху , що збірка перевірка є найбільш корисним для лову дурних помилок (в результаті стрімкого руху)
Джастін

1
@Justin П'ять хвилин очікування - це п'ятихвилинне очікування, де б воно не було. Один НЕ потрібно , щоб вирватися NERF мечі кожен раз , коли ви фіксації. І не рідкість, коли я розбиваю годину або близько того на роботу на кілька комітетів, які є кожними концептуальними одиницями один одного - "ввести код послуги відпочинку", а потім "здійснити код для сторінки, що обслуговується", як дві окремі коміти (не кажучи вже про налаштування css як чергову фіксацію). Якщо на кожну з них було потрібно 5 хвилин, 1/6 мого часу витрачаю на очікування тестів. Це призведе до збільшення

5 хв чекати, щоб запустити тести одиниці? Я відчуваю, що проекти, над якими ви працюєте, повинні бути розбиті на більш дрібні компоненти.
user441521

@Justin catching silly mistakes (as a result of rushing)точно. поспішати взагалі - це погана практика в розробці програмного забезпечення. Роберт К. Мартін рекомендує писати код, як робити операцію youtube.com/watch?v=p0O1VVqRSK0
Джеррі Джозеф

10

В принципі, я вважаю, що має сенс заважати людям вносити зміни до основної лінії, які порушують складання. Тобто процес внесення змін до основної гілки вашого сховища повинен вимагати, щоб усі тести все-таки пройшли. Порушення складання просто занадто дорого з точки зору втраченого часу для всіх інженерів проекту робити щось інше.

Однак, конкретне рішення гачок для фіксації не є вдалим планом.

  1. Розробнику доводиться чекати, коли тести запускаються під час фіксації. Якщо розробнику доводиться чекати на своїй робочій станції, щоб усі тести пройшли, ви витратили цінний інженерний час. Інженеру потрібно мати можливість перейти до наступного завдання, навіть якщо йому доведеться переключитися назад, оскільки тести закінчилися невдалими.
  2. Розробники можуть захотіти вчинити зламаний код у гілці. У більшому завданні версія розробника коду може витратити багато часу, не переходячи до стану. Очевидно, об'єднання цього коду в основну лінію було б дуже погано. Але досить важливо, що розробник все ж може використовувати контроль версій для відстеження його прогресу.
  3. Є випадкові вагомі причини пропустити процес і обійти тести.

2
№ 1 скасовується, дозволяючи розробникам здійснювати реєстрацію в особистому відділенні або локальному сховищі. Тільки тоді, коли розробник хоче десь їх код, інші розробники можуть побачити це, що одиничні тести потрібно запустити. Як і у випадку з №1, №2 заборонено лише гачками до основних гілок. №3 ухиляється тим, що А) Будь-яку таку функцію можна відключити, навіть якщо це клопоти (і має бути клопоту) та В) Окремі тести, які не мають змоги, можуть бути відключені.
Брайан

@Brian, я згоден, ти можеш зробити цю роботу. Але намагатися зробити це, заблокувавши гачок на сервері фіксування гачка, не вийде.
Вінстон Еверт

хороші моменти. Breaking the build is simply too costly in terms of lost time for all engineers on the projectЯ б запропонував використовувати якийсь інструмент сповіщення про побудову, щоб уникнути того, як усі інженери закінчують втрачати час на кожну розбиту збірку
Джеррі Джозеф

3

Ні, ви не повинні, як вказували інші відповіді.

Якщо ви хочете мати базу коду, яка гарантовано не матиме провальних тестів, ви можете замість цього розробитись у гілках функцій і зробити запити в master. Тоді ви можете визначити передумови для прийняття цих запитів на виклик. Перевага полягає в тому, що ви можете швидко натиснути, а тести працюватимуть у фоновому режимі.


2

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

Але є й інші способи досягнення послідовної основної галузі. Ось одна пропозиція, трохи схожа на жилку закритих реєстрацій в TFS, але яка є узагальненою для будь-якої системи управління версіями з гілками, хоча я здебільшого використовую терміни git:

  • Майте поетапну гілку, до якої ви можете здійснювати злиття лише між вашими гілками розробників та основною гілкою

  • Налаштуйте гачок, який починає чи в черзі збирає, і тестує коміти, виконані на гілці інсценізації, але це не змушує програму чекати

  • Після успішного складання та тестів, автоматично змушуйте головну гілку рухатися вперед, якщо вона актуальна

    Примітка: не зливайтеся автоматично в основну гілку, тому що тестоване злиття, якщо не передні злиття з точки зору основної гілки, може бути невдалим при об'єднанні в основну гілку з коміратами між

Як наслідок:

  • Заборонити людям зобов’язуватись до головної гілки автоматично, якщо ви можете, але також як частину офіційного процесу, якщо є лазівка ​​або якщо це технічно неможливо виконати

    Принаймні, ви можете переконатися, що ніхто не зробить це ненавмисно чи без злості, коли це буде основним правилом. Ніколи не слід намагатися це робити.

  • Вам доведеться вибирати між:

    • Єдина гілка поетапної дії, яка зробить інакше успішним злиття насправді не вдасться, якщо попереднє ще не створене і не перевірене злиття не вдасться

      Принаймні, ви знаєте, яке злиття не вдалося, і хтось його виправить, але злиття між ними не тривіально відстежуються (системою контролю версій) за результатами подальшої збірки та тестів.

      Ви можете подивитися анотацію до файлу (або звинувачувати), але іноді зміна файлу (наприклад, конфігурація) призведе до помилок у несподіваних місцях. Однак це досить рідкісна подія.

    • Кілька розгалужуючих гілок, що дозволить безконфліктним успішним злиттям дістатися до головної гілки

      Навіть у тому випадку, якщо інша гілка інсценування має неконфліктні невдалі злиття. Простежуваність трохи краща, як мінімум випадок, коли одне злиття не очікувало, що вплине зміна від іншого злиття. Але знову ж таки, це досить рідко, щоб не турбуватися про кожен день чи кожен тиждень.

      Щоб безконфліктне злиття проводилося більшу частину часу, важливо розумно розділити послідовні гілки, наприклад, за командою, шаром або за складовою / проектом / системою / рішенням (як це ви назвали).

      Якщо головну гілку тим часом переадресували до іншого злиття, вам доведеться знову об'єднатись. Сподіваємось, це не проблема неконфліктного злиття або дуже мало конфліктів.

У порівнянні з зареєстрованими реєстраційними перевагами, перевага тут полягає в тому, що ви маєте гарантію діючої основної гілки, тому що головній гілці дозволяється лише рухатися вперед, а не автоматично об'єднувати ваші зміни з тим, що було зроблено між ними. Отже, третій момент - істотна відмінність.


Але сенс мати робочу гілку не (як правило) для забезпечення стабільного випуску, а в тому, щоб скоротити обмолот, викликаний розробниками, які працюють разом в одному коді.
Теластин

Не якщо у вас є величезне репо з великими глобально розподіленими командами. Наприклад, Microsoft використовує подібний, більш шаруватий підхід з Windows.
ацелент

2

Я вважаю за краще "пройдені тестові одиниці" бути воротами для подання коду. Однак, щоб зробити цю роботу, вам знадобиться кілька речей.

Вам знадобиться побудова рамки, яка кешує артефакти.

Вам знадобиться тестовий фреймворк, який кешує статус тесту з (успішних) тестових запусків, з будь-якими заданими артефактами.

Таким чином, реєстрація з тестами, що проходять через модуль, буде швидкою (перехресна перевірка від джерела до артефакту, який був створений, коли розробник перевіряв тести перед реєстрацією), ті, хто не має тестів на блоці, будуть заблоковані та розробники, зручно забути перевірити складання перед фіксацією, буде запропоновано пам’ятати про це наступного разу, оскільки цикл компіляції та тестування тривалий.


1

Я б сказав, що це залежить від проекту та обсягу автоматизованих тестів, які виконуються на "коміті".

Якщо тести, які ви хочете запустити в триггері реєстрації, дійсно швидкі, або якщо робочий процес розробника змусив якусь адміністративну роботу після такої реєстрації, я думаю, це не повинно мати великого значення і змусить розробників лише перевіряти у матеріалах, які абсолютно виконують найосновніші тести. (Я припускаю, що ви б запустили лише найосновніші тести на такому триггері.)

І я думаю, що швидкість / робочий процес дозволяє, це не добре підштовхувати зміни до інших розробників, які не виконують тести, - і ви знаєте лише, якщо вони не спрацюють, якщо ви запускаєте їх.

Ви пишете "зобов'язати ... віддаленій гілці" у запитанні, що означало б для мене це: (а) не те, що розробник робить кожні кілька хвилин, тому невелике зачекання може бути дуже прийнятним, і (b) що після така фіксація змін коду може вплинути на інші розробники, тому додаткові перевірки можуть бути в порядку.

Я можу погодитися з іншими відповідями на тему: "не робіть своїх чортів щедріти пальцями під час очікування" такої операції.


1

Розбитих комітетів не слід допускати на багажник , оскільки багажник - це те, що може йти у виробництво. Тому вам потрібно переконатися, що є шлюз, який вони повинні пройти, перш ніж перебувати на багажнику . Однак, порушені комісії можуть бути повністю штрафними в рамках репо, доки він не знаходиться на багажнику.

З іншого боку, вимагаючи від розробників зачекати / виправити проблеми перед тим, як натиснути зміни на сховище, є ряд недоліків.

Деякі приклади:

  • У TDD прийнято виконувати та просувати невдалі тести на нові функції перед тим, як почати реалізовувати функцію
  • Те ж саме стосується повідомлення про помилки, виконуючи та натискаючи невдалий тест
  • Натискання неповного коду дозволяє 2 або більше людей паралельно працювати над функцією
  • Ваша інфраструктура CI може зайняти час перевірки, але розробнику не потрібно чекати
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.