Как подготовить тестовые базы данных для тестов Rails rspec без запуска спецификации rake?
после значительного устранения неполадок я понял, что мне нужно запустить rake spec
один раз (я могу прервать с помощью control-c), прежде чем я смогу запустить rspec напрямую (например, на подмножестве наших спецификаций). Мы бежим рельсы 3.0.7 и RSpec 2.5.0.
очевидно, что rake выполняет некоторые важные задачи настройки базы данных / код (у нас есть пользовательский код в Rakefile rails корневого уровня и, возможно, в других местах).
как я могу запустить rake test database setup tasks / code без запуска 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 на работе, поэтому я постепенно разрабатывал систему для обработки этого. Возможно, это не лучшее решение, но оно работает для меня в моей ситуации, и я всегда ищу лучшие способы делать вещи.
У меня есть тестовая база данных, которую мне нужно было настроить, но также нужны были загруженные данные для наших тестов.
основные задачи устранения неполадок rake-это запустить rake с параметром --trace, чтобы увидеть, что происходит под капюшон. Когда я это сделал, я обнаружил, что запуск 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 rake.
кроме того, если вы обнаружите, что тестовая установка принимает слишком долго (как и в нашем случае), вы также можете сбросить базу данных .формат 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
вызов сбой, потому что БД не может быть удален. Сложная вещь.
обеспеченные решения все требуют для того чтобы нагрузить окружающую среду рельсов, которая, в большинстве случаев, не пожеланное поведение должное к очень большим накладным расходам и очень малой скорости.
DatabaseCleaner
gem также довольно медленно, и это добавляет еще одну зависимость от вашего приложения.после нескольких месяцев огорчения и досады благодаря причинам, приведенным выше, я, наконец, нашел следующее решение, чтобы быть именно то, что мне нужно. Это красиво, просто и быстро. В
spec_helper.rb
:config.after :all do ActiveRecord::Base.subclasses.each(&:delete_all) end
самая лучшая часть о это: он будет очищать только те таблицы, которые у вас есть эффективно задел (нетронутые модели не будут загружены и, следовательно, не появятся в
subclasses
, также причина, почему это не работает до тесты). Кроме того, он выполняется после тестов, поэтому (надеюсь) зеленые точки появятся сразу.единственным недостатком этого является то, что если у вас есть грязная база данных перед запуском тестов, она не будет очищена. Но я сомневаюсь, что это серьезная проблема, так как тестовая база данных обычно не затрагивается внешними тестами.
Edit
видя, как этот ответ приобрел некоторую популярность, я хотел отредактировать его для полноты: если вы хотите очистить все таблицы, даже те, которые не трогал, Вы должны быть в состоянии сделать что-то вроде "хаки" ниже.
Hack 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
чтобы также сначала удалить базу данных)как говорится в комментарии, если мы хотим удалить БД во-первых,
rake db:reset
делает именно это.Я также считаю, что это обеспечивает больше обратной связи по сравнению с
rake db:test:prepare
.