Як ви масштабуєте тестування на інтеграцію?


21

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

На майже 200+ тестах інтеграції ми вже натискаємо позначку 1hr, щоб виконати повний тестовий пробіг (на машині Dev Dev), і це негативно впливає на здатність розробника терпіти запуск всього пакету як частину рутинних процесів push. Що впливає на мотивацію бути дисциплінованими щодо того, щоб добре їх створити. Ми інтегруємо тест лише ключових сценіорів спереду та назад, і використовуємо середовище, яке відображає виробництво, яке будується з нуля кожного тестового циклу.

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

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

Щоб було зрозуміло, намагатися не допустити, щоб це стало дискусією про тестування одиниць порівняно з тестуванням інтеграції (що ніколи не слід торгувати). У цьому продукті ми проводимо тестування обох модулів за допомогою тестування TDD AND інтеграції. Насправді ми проводимо тестування інтеграції на різних шарах архітектури служб, де ми маємо сенс, тому що нам потрібно перевірити, куди ми вносимо порушення змін при зміні шаблонів нашої архітектури на інші області система. 

Трохи про наш стек технологій. В даний час ми перевіряємо емуляцію (процесор та пам'ять), щоб виконувати наші тести від кінця до кінця. До складу якого входять веб-сервіси Azure REST, що створюють резервний сервер noSql (ATS). Ми моделюємо наше виробниче середовище, працюючи в Емуляторі робочого столу Azure + IISExpress. Ми обмежені одним емулятором та одним локальним сховищем для бекенда на кожній розробниковій машині.

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

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

Довгий і короткий з них полягає в тому, що: хоча ми могли б оптимізувати пропускну здатність кожного тесту (навіть якщо на цілих 30% -50% кожен), ми все ще не будемо ефективно масштабувати найближчим часом за допомогою декількох сотень тестів. 1 годину зараз ще набагато перевищує людський терпимість, нам потрібен порядок покращення загального процесу, щоб зробити його стійким.

Отже, я досліджую, які методи та стратегії ми можемо використовувати, щоб різко скоротити час тестування.

  • Писати менше тестів - це не варіант. Дозвольте не обговорювати цю тему в цій темі.
  • Використання більш швидкого обладнання - це безумовно варіант, хоча і дуже дорогий.
  • Виконання груп тестів / сценаріїв на окремому апараті паралельно також визначено кращим варіантом.
  • Створення групування тестів навколо функцій та сценаріїв, що розробляються, є правдоподібним, але в кінцевому підсумку не є надійним, щоб довести повне охоплення або впевненість, що система не впливає на зміни. 
  • Запуск у хмарному режимі інсценування замість запуску в емуляторі робочого столу технічно можливий, хоча ми починаємо додавати час тестування до тестових прогонів (~ 20 хвилин кожний на початку тестового запуску для розгортання матеріалу).
  • Поділ компонентів системи на незалежні логічні частини є певною мірою правдоподібним, але ми очікуємо обмежений пробіг на цьому, оскільки, як очікується, з часом збільшуватимуться взаємозв'язки між компонентами. (тобто зміна не може вплинути на інших несподіваними способами - як це часто буває, коли система розробляється поступово)

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

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

[Оновлення: 16.12.2016: Ми закінчили інвестувати більше в паралельне тестування ІС, для обговорення результатів: http://www.mindkin.co.nz/blog/2015/12/16/16-jobs]


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

Схоже, це переходить до дискусії про те, що є, а що не є інтеграційним тестуванням, і нерозуміння людьми одиничного тестування та інтеграційного тестування, о хлопче!
Jezz Santos

Відповіді:


9

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

Довга коротка історія, ви цього не робите. Повноцінні тести на інтеграцію зростають в експоненціальній мірі зростання вашої кодової бази (більше коду означає більше тестів, а більше коду означає, що всі тести триватимуть довше, оскільки для їхньої роботи є більше "інтеграції"). Я заперечую, що все, що знаходиться в діапазоні «годин», втрачає більшість переваг безперервної інтеграції, оскільки циклу зворотного зв'язку не існує. Навіть на порядок покращення масштабів недостатньо для того, щоб ви отримали добро - і це ніде не може зробити вас масштабованим.

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


Я згоден. Тести блоку набагато масштабніші і підтримують швидший цикл зворотного зв'язку.
Брендон

8
Можливо, ви пропустили цю точку. В ОП вже проводяться широкі тестування, а також інтеграційне тестування. Блокові тести ніколи не замінюють тести інтеграції. Різні інструменти, різні практики, різні цілі, різні результати. Ніколи не йдеться про те чи інше.
Джез Сантос

1
Додано чіткість до публікації, щоб чітко сказати, що ми будуємо цей продукт за допомогою TDD, тому у нас вже є тисячі одиничних тестів, підкріплених відповідними тестами інтеграції. .
Джез Сантос

8

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

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

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


Хороша ідея! дивлячись на таку стратегію, але з деякими інструментами, які допомагають розподілити тестування
Jezz Santos

4

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

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

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

Тож ми спробували інкрементальне посилання на наші сервери побудови, але це було ненадійно. Іноді це може дати помилкові негативи і не вдасться докладатись до деяких зобов’язань, тільки щоб потім досягти успіху в повній відбудові. Гірше, що іноді вони даватимуть помилкові позитиви та повідомлятимуть про успіх збірки, лише для розробника, щоб об'єднати розбиту збірку в основну гілку. Тому ми поверталися до відновлення всього щоразу, коли розробник витісняв зміни зі свого приватного відділення.

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

Побічний проект під час очікування, інтегруйте пізніше

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

Розбирання вихідних файлів вручну, щоб з'ясувати, що потрібно відновити / перезапустити

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

Ця ж стратегія повинна застосовуватися і до інтеграційних тестів. Просто рекурсивно розбирайте вихідні файли, щоб з’ясувати, від яких файлів залежить інтеграційні тести (наприклад: importу Java,#includeв C або C ++) на стороні сервера, і файли, що включаються / імпортуються з цих файлів тощо, будують повний графік файлу залежності залежності / імпорту для системи. На відміну від розбору збірок, який утворює DAG, графік повинен бути непрямим, оскільки він зацікавлений у будь-якому зміненому файлі, що містить код, який може бути виконаний побічно *. Перезапустіть тест інтеграції лише у тому випадку, якщо будь-який із цих файлів у графіку для інтеграційного тесту інтеграції змінився. Навіть для мільйонів рядків коду було легко зробити цей аналіз за менше хвилини. Якщо у вас є інші файли, крім вихідного коду, які можуть впливати на тест інтеграції, наприклад файли вмісту, можливо, ви можете записати метадані в коментар у вихідний код із зазначенням цих залежностей у тестах інтеграції, так що якщо ці зовнішні файли змінюватимуться, тести також перезапустити.

* Наприклад, якщо test.c включає foo.h, який також включений foo.c, то зміна на test.c, foo.h або foo.c повинно позначити інтегрований тест як необхідний новий пробіг.

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


3

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

В якості прикладу взяти сховище з методом set(key,object), get(key). Це сховище широко використовується у всій вашій кодовій базі. Усі методи, які залежать від цього сховища, будуть перевірені підробленим сховищем. Тепер вам потрібні лише два інтеграційні тести, один для набору та один для отримання.

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

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

Практично все інше можна перевірити на одиниці з використанням заглушених / макетованих / підроблених / в пам’яті для залежностей.


1
Цікава перспектива. Наші інтеграційні тести не намагаються перевірити кожну перестановку кожного параметра кожного дзвінка ReST. На наш погляд, це не інтеграційне тестування. Вони працюють за ключовими сценаріями "в кінці до кінця" через API, який, в свою чергу, потрапляє в різні резервні магазини та інші системи. Мета полягає в тому, щоб у міру зміни API визначити, які сценарії потребують уваги (тобто більше не працювати, як очікувалося).
Джез Сантос

1
У нас є інтеграційні тести на різних рівнях в архітектурі. У вашому прикладі у нас є одиничні тести для класів, які отримують доступ до сховища даних, тому ми знаємо, що вони здійснюють правильні дзвінки до нашого сховища даних, у нас є інтеграційні тести, щоб налаштувати копію наших магазинів і перевірити, чи правильно вони читають і записують дані. з магазином. Тоді ми використовуємо ці класи даних у API REST, які ми створюємо за допомогою тестів на одиниці, а потім тести інтеграції, які запускають веб-сервіс та зателефонують, щоб переконатися, що дані надходять ззаду на фронт та навпаки. Ви припускаєте, що у нас тут занадто багато тестів?
Jezz Santos

Я оновив свою відповідь як відповідь на ваші коментарі.
Есбен Сков Педерсен

2

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

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

Ще один варіант, який слід розглянути, - це рішення, розроблене спочатку 2002 р. Під назвою Virtualization Service. Це створює віртуальне середовище, імітуючи взаємодію модулів із наявними ресурсами для цілей тестування у складному середовищі DevOps або Agile.

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


Хоча це може працювати (якщо систему можна розділити на такі модулі, але не всі продукти можуть) - це було нормою на деякий час, вона фактично затримує інтеграцію, тим самим втрачаючи всі переваги CI / CD. Якийсь протилежний, ти не думаєш? Проблеми, виявлені при такому інтеграційному тестуванні, не можуть бути легко та швидко підібрані до конкретного комітету, тому потребують повного дослідження від нуля, як і помилки, що надходять із виробництва (і ви знаєте, наскільки дорожче їх вирішити).
Дан Корнілеску

1

Чи вимірювали ви кожен тест, щоб побачити, де проводиться час? А потім виміряйте продуктивність кодової бази, якщо є особливо повільний біт. Чи загальна проблема є одним із тестів чи розгортання, чи обом?

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

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

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

У нас була схожа проблема із запуском інструменту статичного аналізу на основі безпеки. Повні запуски займуть віки, тому ми перенесли його за допомогою розробника, який здійснює інтеграцію (тобто у нас була система, де розробник сказав, що вони закінчені, він об'єднався в гілку "рівня 2", де проводилось більше тестування, включаючи perf тести. Коли це було завершено, він об'єднався у відділення QA для розгортання. Ідея полягає у видаленні регулярних запусків, які постійно відбуватимуться для запусків, що робляться вночі - розробники отримають результати вранці, і це не вплине на їх розвиток фокусування до пізніше в їхньому циклі розробки).


1

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

Це, однак, створює нову проблему - розробники не отримують негайного зворотного зв’язку, і зламані збірки можуть залишитися непоміченими. Щоб виправити це, важливо, щоб вони знали, що щось порушено. Побудувати засоби сповіщення, такі як Catlight або TeamCity-сповіщувач лотка, може бути дуже корисним.

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

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


0

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

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

Магазин Java, в якому я працюю, використовує такий підхід, і нас рідко чекають очікування запуску тестів на інтеграцію.


Дякую, але я думаю, що ми не однаково розуміємо мету та застосування інтеграційного тестування в цьому контексті. Можливо, ви пов'язуєте тестування інтеграції з тестуванням одиниць.
Jezz Santos

0

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

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

  • у разі успіху він автоматично здійснює зміни у гілці
  • у разі невдачі він повідомляє відповідних відправників про повторну оцінку їх змін

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

Одним із таких прикладів є система накладки на основі Герріта / Зууля, що використовується OpenStack .

Ще один - ApartCI ( відмова - я його творець і засновник компанії, що її пропонує).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.