90

重要なトラブルシューティングの後、rake specrspecを直接実行する前に(たとえば、仕様のサブセットで)、一度実行する必要があることがわかりました(control-cで中止できます)。Rails3.0.7とRSpec2.5.0を実行しています。

明らかに、rakeはいくつかの重要なデータベースセットアップタスク/コードを実行しています(ルートレベルのレールRakefileおよび場合によっては他の場所にカスタムコードがあります)。

実行せずにraketestデータベースのセットアップタスク/コードを実行するにはどうすればよいrake specですか?

ファイルのサブセットでrspecを実行できることに加えて、specjourを使用してスペックを複数のコアに分散しています(LAN全体にスペックを分散することはまだ成功していません)が、rspecを実行する場合と同じ動作が見られます直接:rake specspecjourが機能する前に、各テストデータベース(2つのコアを想定)で実行する必要があります。

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には、テスト用のこのエントリがあります(並列テストgemで一般的です):

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

parallel_testsはデータベースを正しく設定しているようですが、仕様の多くは失敗しています。

また、実行するspecjour prepareと、Postgresはデータベースを見つけることができないというエラーをログに記録しますが、データベースは作成されます(テーブルなし)。その後の実行では、エラーはログに記録されませんが、テーブルも作成されません。私の問題全体が単なるバグである可能性があるprepareので、githubで報告しました。

.specjour / hooks.rbに設定することで、各specjourテストデータベースで任意のコードを実行できると思いますSpecjour::Configuration.prepare。したがって、実行する必要のあるrakeタスクやその他のコードがあれば、そこで機能する可能性があります。

4

6 に答える 6

186

テストデータベースを削除してから、再作成して移行することをお勧めします。

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環境が読み込まれ、データベース接続が開かれるため、これは機能しません。これにより、prepareDBをドロップできないため、呼び出しが失敗します。トリッキーなこと。

于 2012-06-22T14:53:22.167 に答える
15

職場でのCIシステムのセットアップでも同様の問題が発生したため、これを処理するためのシステムを徐々に構築しました。それは最善の解決策ではないかもしれませんが、私の状況ではうまくいき、私は常に物事を行うためのより良い方法を探しています。

セットアップが必要なテストデータベースがありますが、テストを機能させるためにシードデータをロードする必要もありました。

rakeタスクのトラブルシューティングの基本は、-traceオプションを指定してrakeを実行し、内部で何が起こっているかを確認することです。これを行ったとき、rake仕様を実行すると、カスタム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

これは単なる例であり、私たちの状況に固有であるため、テストデータベースをセットアップするために何をする必要があるかを理解する必要がありますが、rakeの--traceオプションを使用して決定するのは非常に簡単です。

さらに、テストのセットアップに時間がかかりすぎる場合(この場合のように)、データベースを.sql形式にダンプし、テストデータベースに直接mysqlにパイプしてロードさせることもできます。そうすることで、テストデータベースのセットアップから数分節約できます。物事を大幅に複雑にするため、ここでは示しません。古くなることなく適切に生成する必要があるなどです。

HTH

于 2011-05-07T16:48:33.017 に答える
15

提供されているソリューションはすべて、Rails環境をロードする必要がありますが、オーバーヘッドが非常に大きく、速度が非常に遅いため、ほとんどの場合、望ましい動作ではありません。DatabaseCleanergemもかなり遅く、アプリに別の依存関係を追加します。

上記の理由のおかげで何ヶ月にもわたる悔しさと悩みの末、私はついに次の解決策がまさに私が必要としているものであることに気づきました。それは素晴らしく、シンプルで速いです。でspec_helper.rb

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

これについての最良の部分は次のとおりです。効果的に触れたテーブルのみがクリアされます(触れられていないモデルはロードされないため、に表示されません。また、テスト前にsubclassesこれが機能しない理由もあります)。また、テスト後に実行されるため、(うまくいけば)緑色の点がすぐに表示されます。

これの唯一の欠点は、テストを実行する前にダーティデータベースがある場合、データベースがクリーンアップされないことです。しかし、テストデータベースは通常、外部のテストからは影響を受けないため、これが大きな問題であるとは思えません。

編集

この回答がある程度人気を博しているので、完全を期すために編集したいと思いました。触れていないテーブルも含めてすべてのテーブルをクリアしたい場合は、以下の「ハック」のようなことができるはずです。

subclassesハック1-メソッドのすべてのモデルをプリロードする

呼び出す前にこれを評価して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
于 2013-08-04T03:37:08.297 に答える
7

ActiveRecord::Migration.maintain_test_schema!Rails 4.1以降では、の後にrails_helperを追加するのが最善の解決策のようですrequire 'rspec/rails'

つまり、データベースを準備する必要がなくなることを心配する必要はありません。

https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks

于 2015-05-20T10:00:57.990 に答える
3

スプリング化されたRails4アプリでbin/setupは、通常、私は次のように拡張されます

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

これは、リヴァイアサンの答えに非常に似ていますが、テストDBをシードします。

rake db:setup #データベースを作成し、スキーマをロードし、シードデータで初期化します(
最初にデータベースを削除するためにも 使用します)db:reset

コメントにあるように、最初にDBを削除したい場合は、それをrake db:reset実行します。

また、これはに比べてより多くのフィードバックを提供することもわかりましたrake db:test:prepare

于 2015-07-07T19:56:38.493 に答える
0

テストデータベースを削除することから始めました rake db:drop RAILS_ENV=test

新しいテストデータベースを作成しようとしたときに、ユーザーアカウントがデータベースを所有するアカウントと同じではなかったために問題が発生したため、代わりにPostgreSQLでデータベースを作成しました。

コマンドプロンプトに入力psqlし、以下を実行して、自分のアカウント以外のアカウントを使用するテストデータベースを作成します。 CREATE DATABASE your_database_name OWNER your_db_owner;

次に、テスト環境で移行を実行します。 rake db:migrate RAILS_ENV=test

于 2020-06-15T15:47:14.380 に答える