私はRails-rspec
gemを使用しており、いくつかの仕様(モデル、コントローラーなど)があります。私が走るとき:
bundle exec rake
すべてがテストされます。ただし、データベースが(テスト環境で)作成された直後に(db/seeds.rbから)いくつかのデータをシードすることにより、仕様を改善したいと思います。
私のspec/spec_helper.rbファイルは次のようになります。
ENV["Rails_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/Rails'
require 'capybara/rspec'
require 'Ruby-debug'
# Requires supporting Ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
config.include SpecHelper
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
stub_xmpp_rest_client!
end
config.after(:each) do
DatabaseCleaner.clean
end
config.include Devise::TestHelpers, :type => :controller
config.include Delorean
config.after(:each) { back_to_the_present }
config.include Factory::Syntax::Methods
config.extend ControllerMacros, :type => :controller
end
そうするための最良の方法は何でしょうか?ありがとう。
シードファイルの構成方法によっては、before(:each)
またはbefore(:all)
ブロックからシードファイルをロード/実行できる場合があります。
load Rails.root + "db/seeds.rb"
悪いアイデア!テストデータベースにシードを設定しないでください。工場を使用して、各テスト内にのみそのテストに合格するために必要なレコードを作成します。テストデータベースにシードを設定すると、テストで明示的に指定されていない多くの仮定を行うため、テストの信頼性が低下します。
Db/seeds.rbを自動的にロードするようにrake spec
タスクを設定したので、最初の実行のためにデータベースを設定するためにそれに依存しています。これをRakefileに追加します。
task :spec => "db:seed"
task :cucumber => "db:seed"
その後の実行では、rspec spec
を直接呼び出して、シードステップをスキップし、不要なリロードを回避します。次のようにシードテーブルを無視するようにデータベースクリーナーを構成します。
RSpec.configure do |config|
config.add_setting(:seed_tables)
config.seed_tables = %w(countries roles product_types)
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation, except: config.seed_tables)
end
config.around(:each) do |example|
if example.metadata[:no_transactions]
DatabaseCleaner.strategy = :truncation, {except: config.seed_tables}
else
DatabaseCleaner.strategy = :transaction
end
DatabaseCleaner.start
example.run
DatabaseCleaner.clean
end
end
コミットされたデータが必要なシナリオの場合、次を追加できます。
describe "commit for real", use_transactions: false do
# ...
end
これにより、シードテーブルを除き、サンプルの実行後にすべてが切り捨てられます。 シードテーブルには何も書き込まないことを前提としています!シードデータは通常静的であるため、これは一般的に安全な前提です。
他のすべての通常のシナリオでは、挿入されたレコードをロールバックするためにトランザクションに依存しています。データベースは元の状態に戻り、シードテーブルのデータはそのままです。必要に応じて、ここでシードテーブルに書き込んでも安全です。
シードテーブルを再構築するには、rake spec
を再度実行する必要があります。
Rspecにシードをロードするには、データベースのクリーンアップ後にspec_helperのconfig.before(:suite)にシードを追加する必要があります。
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
load "#{Rails.root}/db/seeds.rb"
end
Rails 4.2.およびRSpec 3.xでは、これが私のRails_helper.rbの外観です。
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
config.before(:all) do
Rails.application.load_seed # loading seeds
end
end
config/initializersフォルダー内のseed.rbファイルをコピーします。したがって、seed.rbファイルはサーバーの起動時に実行されます。
以下のコマンドを実行して、テストデータベースにseed.rbデータを入力します
Rails_ENV = test rake db:seed