Прискорення тестів RSpec у великому додатку Rails


90

У моєму тесті RSpec є програма Rails із понад 2000 прикладів. Зайве говорити, що це велика програма, і є багато чого перевірити. Запуск цих тестів на даний момент дуже неефективний, і тому що це займає так багато часу, ми майже в точці, коли нам не рекомендується писати їх перед натисканням на нову збірку. Я додав --profile до мого spec.opts, щоб знайти найтриваліші приклади, і існує принаймні 10 з них, на виконання яких потрібно в середньому 10 секунд. Це нормально серед вас, експертів RSpec? 10 секунд - це занадто довго для одного прикладу? Я розумію, що з 2000 прикладами знадобиться нетривіальна кількість часу, щоб все ретельно перевірити - але на цей момент 4 години - це трохи смішно.

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


1
Чи є повільні тести інтеграційними тестами? Вони б'ють дБ? Якщо так, то як часто db перезавантажується і чи можете ви знущатися над ним?
Калеб Педерсон,

1
Чи можете ви просто запустити частину специфікацій, які мають відношення до тієї частини, над якою ви працюєте, подібну до автотесту SeattleRB? У вас є сервер безперервної інтеграції, який може запускати всі тести?
Andrew Grimm,

Пам'ятайте також, що всі речі відносні. Я чув "grrr, наш тестовий пакет триває вічно" і 20 хвилин ... і 16-20 годин. Це все в очах спостерігача. 10 секунд для даного тестування часто означає одиничний тест, який став інтеграційним тестом, як зазначено нижче.
Michael Durrant

Пропозиція щодо такого роду проблем: використовуйте perftools.rbразом із тестовою структурою, щоб зрозуміти, на що витрачається більша частина вашого часу. Візьміть 10 найкращих дзвінків і спробуйте їх усунути / зняти. Потім повторюйте, поки не зрадієте.
aledalgrande

Відповіді:


118

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

1. Окремий блок від інтеграційних тестів

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

  1. Переміщення їх (в окремі папки в каталозі специфікацій) - і зміна цілей рейку
  2. Позначення їх тегами (rspec дозволяє позначити тести)

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

Тест інтеграції - це тест, який включає зовнішні залежності (наприклад, База даних, WebService, Черга, а деякі можуть аргументувати FileSystem). Модульний тест просто перевіряє конкретний елемент коду, який ви хочете перевірити. Він повинен працювати швидко (можливо 9000 за 45 секунд), тобто більша його частина повинна працювати в пам'яті.

2. Перетворити інтеграційні тести на модульні

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

  1. Використовуйте глузувальну структуру замість реального ресурсу. Rspec має вбудований механізм насмішок.
  2. Запустіть rcov на наборі модульних тестів. Використовуйте це, щоб оцінити, наскільки ретельним є ваш набір модульних тестів.

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

3. Не використовуйте світильники

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

4. Додайте перевірки, щоб зупинити одиничні тести, які стають інтеграційними

Тепер, коли у вас є швидше тестування, час перевіряти, щоб ЗУПИНИТИ це повторюватися.

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

Ви також можете спробувати сполучення та TDD, що може допомогти вашій команді писати швидші тести, оскільки:

  1. Хтось перевіряє - щоб ніхто не лінувався
  2. Правильний TDD вимагає швидкого зворотного зв'язку. Повільні тести просто роблять все це болючим.

5. Використовуйте інші бібліотеки, щоб подолати проблему

Хтось згадав spork (пришвидшує час завантаження тестового набору під rails3), hydra / Паралельні тести - для паралельного запуску модульних тестів (на декількох ядрах).

Це, мабуть, слід використовувати ОСТАННІЙ. Ваша справжня проблема - це повністю на кроках 1, 2, 3. Вирішіть це, і ви зможете краще виграти додаткову інфраструктуру.


Чудова відповідь. Цілком вірно, що жоден просунутий інструмент не може допомогти швидко виконати погані тести. Тож спробуйте писати лише хороші.
Юра Омельчук

5
Я не згоден з вашим третім пунктом, що ви не повинні користуватися світильниками. Якщо їх правильно використовувати, вони швидші за фабрики, оскільки вам не потрібно створювати об’єкти. Ваші дані є там, вам не потрібно їх створювати з кожним тестом.
wallerjake

3
Це про те, що фабрики працюють швидше - це жарт, так?
Mike Szyndel

Прискорити тести шляхом вибіркового уникнення фабрики - robots.thoughtbot.com/…
geekdev

16

Щоб отримати чудову кулінарну книгу щодо покращення роботи тестового набору, перегляньте презентацію Grease Your Suite .

Він документує 45-кратне прискорення під час роботи набору тестів, використовуючи такі методи, як:


Мені подобаються посилання, але не презентація. Карти покажчика для чиєїсь промови - це спонукання доповідача заповнити основну частину презентації.
Brian Maltzan

Ця презентація більше не готується. fast_context пришвидшує декілька блоків, що повинні бути. quickerclip (це посилання також мертве), мабуть, пришвидшує скріпки. Hydra застаріла для паралельних_тестів та Gorgon. bootnap має налаштування файлової системи і тепер входить до складу Rails. Останні версії Ruby покращили виділення та GC.
повторення

5

Ви можете використовувати Spork. Він має підтримку 2.3.x,

https://github.com/sporkrb/spork

або ./script/spec_server, який може працювати для 2.x

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


Spork чудовий. Він також працює на Rails 3, з невеликим хакерством. Але одне, що слід зазначити у Spork on Rails 3, це те, що він, здається, не забирає змін у контролерах, тому вам доведеться перезапускати його так часто. Але як би там не було, Spork справді чудовий, покращення швидкості тестів дуже значне.
AboutRuby

4
Spork призначений лише для прискорення запуску, а не тестів. Отже, з великою кількістю специфікацій перевага незначна.
Reactormonk

На відміну від наведених вище коментарів, spork можна використовувати для прискорення тестів, а також запуску відповідно до railscast railscasts.com/episodes/285-spork . Помітно покращив мій набір тестів rspec на дуже великій програмі. (Скорочено зі 192 секунд до 10 секунд!)
jamesc

3

10 секунд на приклад здається дуже довгим. Я ніколи не бачив специфікації, яка займала більше однієї секунди, а більшість - набагато менше. Ви тестуєте мережеві з'єднання? База даних пише? Файлова система пише?

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

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


так, якщо це буде 10 секунд, я б його профіль і побачив, де вузьке місце
rogerdpack

1
У мене величезний проект, і проведення одного тесту rspec займає близько 15-20 секунд.
ExiRe

2

Кілька людей згадували Гідру вище. Ми використовували це з великим успіхом у минулому. Нещодавно я задокументував процес запуску гідри: http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

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



0

швидше_запит дорогоцінний камінь може вам допомогти. Окрім того, ваш єдиний спосіб - це (як і ви) профілювати та оптимізувати, або використовувати спортивний або щось, що паралельно запускає ваші специфікації для вас. http://ruby-toolbox.com/categories/distributed_testing.html


0

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

https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581

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


-4

Видаліть наявний набір тестів. Буде неймовірно ефективним.

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