0

複数のプロセスを生成してデータをフェッチし、単一のデータベーステーブルを更新することで、外部ソースからデータを取り込むRailsシステムを作成しています。同時実行の問題を探すためにフェッチ/書き込みプロセスをエミュレートする複数のプロセスを生成するRSpecテストを作成したいと思います。

短い質問

RSpecテストでテーブルを初期化して、外部プロセスがテーブルの内容を確認できるようにするにはどうすればよいですか?(少なくとも、それは正しい質問だと思います。詳細については読んでください...)

長い形式

私のRSpecテストの一般的な構造は次のとおりです。

it 'external task should update the correct records' do
  initialize_my_model_table_with_some_records
  spawn_external_tasks_to_update_records
  # wait for spawned processes to complete
  Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
  validate_results
end

ただし、外部プロセスは常にモデルテーブルを空と見なします(デバッグ印刷によって確認されます)。その後、テーブルの更新は失敗します。

これは、RSpecがテーブルをロック下に保持しているため、テストの完了後にロールバックを実行できるためだと確信しています。

だから(短い質問を繰り返すために):外部プロセスがテーブルの初期化された内容を見ることができるように、RSpecテストでテーブルを初期化するにはどうすればよいですか?

編集#2

次のテストに入ると、テーブルは前の(外部)プロセスがテーブルを離れた状態になっていることに気付きました。これは理にかなっています。RSpecはテーブルを「認識している」状態にしかロールバックできないため、外部プロセスによって行われた変更は保持されます。

これは解決策を示唆しています。before(:all)を使用してテーブルを明示的に初期化することが機能しているようです。しかし、これは最もクリーンなアプローチですか?

環境

  • Rubyバージョン1.9.3(x86_64-darwin10.8.0)
  • pg(0.13.2)
  • レール(3.2.1)
  • rspec(2.9.0)
  • rspec-rails(2.9.0)
4

1 に答える 1

0

RSpecがテストを実行すると、トランザクションの下でデータベースがロックされ、テスト後にロールバックできるようになります。その結果、外部プロセスは、RSpecがデータベースに加えた変更を認識しません。また、それに応じて、外部プロセスがデータベースに加えた変更は、RSpecテスト後にロールバックされません。

これに対する1つの例外は、内部before(:all)after(:all)ブロックです。RSpecが行った変更は、外部プロセスに表示されます。

したがって、OPの例は次のように機能させることができます。

describe 'with external tasks' do
  before(:all)
    initialize_my_model_table_with_some_records
  end
  after(:all)
    reinitialize_my_model_table
  end

  it 'should update the correct records' do
    spawn_external_tasks_to_update_records
    # wait for spawned processes to complete
    Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
    validate_results
  end
end
于 2012-06-26T18:04:19.383 に答える