Як підготувати тестову базу даних для тестування Rails rspec без запуску специфікацій граблів?


83

Після значного усунення несправностей я зрозумів, що мені потрібно запустити rake specодин раз (я можу перервати за допомогою control-c), перш ніж я зможу запустити rspec безпосередньо (наприклад, на підмножині наших специфікацій). Ми використовуємо Rails 3.0.7 і RSpec 2.5.0.

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

Як я можу запустити завдання / код налаштування бази даних тестового рейку без запуску rake spec?

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

rake spec TEST_ENV_NUMBER=1
control-c (after tests start)
rake spec TEST_ENV_NUMBER=2
control-c (after tests start)
specjour

Примітка: мій файл config / database.yml містить цей запис для тестування (як це звичайно для паралельних тестувань самоцвітів):

test:
  adapter: postgresql
  encoding: unicode
  database: test<%=ENV['TEST_ENV_NUMBER']%>
  username: user
  password:

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

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

Я думаю, що я можу запустити довільний код на кожній тестовій базі даних specjour, встановивши Specjour::Configuration.prepareв .specjour / hooks.rb, тому, якщо є якісь рейкові завдання або інший код, який мені потрібно запустити, він може там працювати.

Відповіді:


14

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

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

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

Ось приклад того, що ми робимо.

desc "Setup test database - drops, loads schema, migrates and seeds the test db"
task :test_db_setup => [:pre_reqs] do
  Rails.env = ENV['RAILS_ENV'] = 'test'
  Rake::Task['db:drop'].invoke
  Rake::Task['db:create'].invoke
  result = capture_stdout { Rake::Task['db:schema:load'].invoke }
  File.open(File.join(ENV['CC_BUILD_ARTIFACTS'] || 'log', 'schema-load.log'), 'w') { |f| f.write(result) }
  Rake::Task['db:seed:load'].invoke
  ActiveRecord::Base.establish_connection
  Rake::Task['db:migrate'].invoke
end

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

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

HTH


Так, я запустив rake spec за допомогою --trace і спробував відтворити деякі його завдання в моєму підготовляючому гачку specjour, але це ще не спрацювало. Я потенційно міг би написати абсолютно окреме завдання на рейк, щоб налаштувати ситуацію, але це ще один крок, якого я сподівався уникнути.
gerry3

169

Я б рекомендував скинути вашу тестову базу даних, потім створити її та перенести:

bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test

Після цих кроків ви можете запустити свої специфікації:

bundle exec rspec spec

gerry3 зазначив, що:

Більш просте рішення - просто запустити rake db:test:prepare

Однак, якщо ви використовуєте PostgreSQL, це не спрацює, оскільки середовище rails завантажується, що відкриває підключення до бази даних. Це спричиняє помилку prepareвиклику, оскільки БД не можна скинути. Хитра штука.


47
Більш просте рішення - просто запустити rake db:test:prepare.
gerry3

7
У мене немає проблем із запуском rake db:test:preparePostgres. Ви, мабуть, бачите свою проблему з якоїсь іншої причини.
gerry3

Якщо db: test: RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load
priprema

11
Схоже rake db:test:prepare, застарілий у Rails 4.
Markquezada

8
Ви можете bundle exec rake db:drop db:create db:schema:load RAILS_ENV=test
зв'язати

14

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

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

config.after :all do
  ActiveRecord::Base.subclasses.each(&:delete_all)
end

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

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

Редагувати

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

Хак 1 - попереднє завантаження всіх моделей для subclassesметоду

Оцініть це перед викликом subclasses:

Dir[Rails.root.join("app", "models", "**", "*.rb")].each(&method(:require))

Зверніть увагу, що цей метод може зайняти деякий час!

Хак 2 - обрізання таблиць вручну

ActiveRecord::Base.connection.tables.keep_if{ |x| x != 'schema_migrations' }

отримає всі назви таблиць, з тими ви зможете зробити щось на зразок:

case ActiveRecord::Base.configurations[Rails.env]["adapter"]
when /^mysql/, /^postgresql/
  ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")
when /^sqlite/
  ActiveRecord::Base.connection.execute("DELETE FROM #{table_name}")
  ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table_name}'")
end

Охайно! Це досить корисно.
дивовижність


3

У весняному додатку Rails 4 мій файл, bin/setupяк правило, доповнено

puts "\n== Preparing test database =="
system "RAILS_ENV=test bin/rake db:setup"

Це дуже схоже на відповідь Левіатана , плюс засівання тестової БД, як

rake db:setup # Створіть базу даних, завантажте схему та ініціалізуйте насіннєвими даними
(використовуйте,
db:reset щоб спочатку скинути базу даних)

Як зазначається в коментарі, якщо ми хочемо спочатку скинути БД, rake db:resetробить саме це.

Я також вважаю, що це забезпечує більше відгуків у порівнянні з rake db:test:prepare.


0

Я розпочав із скидання бази даних тестів rake db:drop RAILS_ENV=test

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

введіть psqlкомандний рядок, а потім запустіть наведене нижче, щоб створити тестову базу даних, яка використовує обліковий запис, відмінний від вашого власного. CREATE DATABASE your_database_name OWNER your_db_owner;

потім запустіть свої міграції в тестовому середовищі. rake db:migrate RAILS_ENV=test

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