Как подготовить тестовые базы данных для тестов Rails rspec без запуска спецификации rake?
после значительного устранения неполадок я понял, что мне нужно запустить rake spec
один раз (я могу прервать с control-c), прежде чем я смогу запустить rspec напрямую (например, на подмножестве наших спецификаций). Мы запускаем Rails 3.0.7 и RSpec 2.5.0.
очевидно, что rake выполняет некоторые важные задачи / код настройки базы данных (у нас есть пользовательский код в корневом уровне rails Rakefile и, возможно, в других местах).
как я могу запустить задачи / код установки тестовой базы данных rake без запуска 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
Примечание: моя конфигурация / база данных.yml имеет эту запись для теста (как обычно для параллельного тестирование драгоценных камней):
test:
adapter: postgresql
encoding: unicode
database: test<%=ENV['TEST_ENV_NUMBER']%>
username: user
password:
parallel_tests кажется, правильно настроить свои базы данных, но многие из наших спецификаций терпят неудачу.
Я должен также упомянуть, что работает specjour prepare
заставляет Postgres регистрировать ошибки, которые он не может найти базы данных, но создает их (без таблиц). При последующем запуске ошибки не регистрируются, но и таблицы не создаются. Вполне возможно, что вся моя проблема-это просто ошибка prepare
, поэтому я сообщил об этом на github.
Я думаю, что я могу запустить произвольный код в каждой тестовой базе данных specjour, установив Specjour::Configuration.prepare
in .specjour / крючки.rb, поэтому, если есть какие-либо задачи rake или другой код, который мне нужно запустить, он может работать там.
5 ответов
У меня была аналогичная проблема с настройкой системы CI на работе, поэтому я постепенно разработал систему для обработки этого. Возможно, это не лучшее решение, но оно работает на меня в моей ситуации, и я всегда ищу лучшие способы сделать что-то.
У меня есть тестовая база данных, которую мне нужно настроить, но также нужны данные, загруженные для наших тестов.
основы устранения неполадок задачи грабли, чтобы запустить грабли с параметром --trace, чтобы увидеть, что происходит под капюшон. Когда я сделал это, я обнаружил, что running rake spec сделал ряд вещей, которые я мог бы воспроизвести (или изменить, как я считал нужным) в пользовательской задаче rake.
вот пример того, что мы делаем.
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
Это только пример и специфичный для нашей ситуации, поэтому вам нужно выяснить, что нужно сделать, чтобы получить настройку тестовой БД, но это довольно легко определить с помощью опции --trace рейка.
кроме того, если вы обнаружите, что тестовая настройка выполняется слишком долго (как и в нашем случае), вы также можете сбросить базу данных .SQL формат и имеют тестовую базу данных трубу его непосредственно в mysql для загрузки. Таким образом, мы экономим несколько минут на настройке тестовой БД. Я не показываю это здесь, потому что это существенно усложняет вещи - его нужно генерировать правильно, не устаревая и т. д.
HTH
Я бы рекомендовал удалить тестовую базу данных, затем повторно создать ее и перенести:
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
вызов сбой, потому что DB не может быть удален. Сложная вещь.
обеспеченные решения все требуют, что нагружают окружающую среду рельсов, которая, в большинстве случаев, не пожеланное поведение должное к очень большим накладным расходам и очень малой скорости. DatabaseCleaner
gem также довольно медленный, и он добавляет еще одну зависимость к вашему приложению.
после нескольких месяцев огорчения и досады благодаря причинам, приведенным выше, я, наконец, нашел следующее решение, которое мне нужно. Это красиво, просто и быстро. В 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))
обратите внимание, что это метод может занять некоторое время!
Hack 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
похоже, что в Rails 4.1+ лучшим решением является просто добавить ActiveRecord::Migration.maintain_test_schema!
в вашем rails_helper после require 'rspec/rails'
.
т. е. вам больше не нужно беспокоиться о том, чтобы подготовить базу данных.
https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks
в приложении spring-ified Rails 4, my bin/setup
обычно дополняется, чтобы содержать
puts "\n== Preparing test database =="
system "RAILS_ENV=test bin/rake db:setup"
это очень похоже на Левиафан, плюс засев тестовой БД, как
rake db:setup
# создайте базу данных, загрузите схему и инициализируйте начальные данные
(используйтеdb:reset
чтобы также сначала удалить базу данных)
как говорится в комментарии, если мы хотим удалить DB во-первых, rake db:reset
делает именно это.
Я также считаю, что это обеспечивает больше обратной связи по сравнению с rake db:test:prepare
.