1. ホーム
  2. ruby-on-rails

[解決済み] rake spec を実行せずに Rails rspec テスト用のデータベースを準備するにはどうしたらいいですか?

2023-04-11 17:12:45

質問

重要なトラブルシューティングの後、 私は rake spec を一度実行してから (control-c で中断できます)、rspec を直接 (たとえば仕様のサブセットに対して) 実行する必要があることを理解しました。私たちは Rails 3.0.7 と RSpec 2.5.0 を実行しています。

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

を実行せずに rake のテストデータベースセットアップタスク/コードを実行するにはどうしたらよいでしょうか。 rake spec ?

ファイルのサブセットに対してrspecを実行できることに加えて、私は specjour を使用して複数のコアに spec を分散させていますが (LAN への分散はまだ成功していません)、rspec を直接実行する場合と同じ動作が見られます。私は rake spec を各テスト データベース (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にはtestの項目があります(並列テスト用gemによくあることです)。

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に設定することで、各specjourテストデータベース上で任意のコードを実行できると思いますので、実行したいrakeタスクなどがあればそこで動くかもしれませんね。

どのように解決するのか?

私は職場でCIシステムのセットアップに同じような問題を抱えていたので、徐々にこれを処理するシステムを作り上げました。 これはベストな解決策ではないかもしれませんが、私の状況ではうまくいっていますし、私はいつもより良い方法を探しています。

私は、セットアップが必要なテスト データベースを持っていますが、テストが機能するようにシード データをロードする必要がありました。

rakeタスクのトラブルシューティングの基本は、フードの下で何が起こっているかを見るために、-traceオプションでrakeを実行することです。 これを実行したとき、私は 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

これはあくまで例であり、私たちの状況に特有のものです。したがって、テスト用データベースをセットアップするために何が必要かを把握する必要がありますが、rakeの-traceオプションを使用すれば、非常に簡単に判断できます。

さらに、もしテストのセットアップに時間がかかりすぎていると感じたら (私たちの場合のように)、データベースを .sql 形式にダンプし、テストデータベースがそれを直接 mysql にパイプしロードするようにすることもできます。 この方法で、テスト用データベースのセットアップにかかる時間を数分短縮することができます。 この方法は物事をかなり複雑にしてしまうので、ここでは紹介しませんが、古くならないように適切に生成する必要があります。

ありがとうございました。