私のアプリケーションには、複雑で長時間実行されるdelay_jobプロセスがあります。 Rspecを使用して、プロセスで使用される個々のメソッドとクラスをテストしていますが、さまざまなテストデータを使用して、エンドツーエンドのバックグラウンドジョブの多くを実行したいと思っています。
これに関するdelay_job wikiには何も見つかりませんでした。このSO質問は興味深いようですが、ここで何が起こっているのか本当に理解できませんでした。 テストする最良の方法は何ですか? rSpecを使用したdelay_jobチェーン?
ファクトリーでテストデータを簡単に設定して、バックグラウンド処理を開始するクラスを呼び出すことができます。テストが完了するまでに長い時間がかかると思います。
編集された背景コード
class Singleplex
def perform(batch_id,user)
batch = start_batch(batch_id,user)
... do lots of stuff ...
end
handle_asynchronously :perform, queue: :singleplex, :run_at => Proc.new { 1.second.from_now }
spec/factories/batches.rb
FactoryGirl.define do
factory :batch do
batch_type 'singleplex'
name 'valid panel'
status 'ready'
end
factory :batch_detail do
chrom 7
chrom_start 140435012
chrom_end 140435012
target_offset 150
padding 4
primer3_parameter_id 1
snp_mask 't'
status 'ready'
batch
end
end
次に、このようにテストを実行します
describe Batch do
it 'runs Singleplex for a valid panel' do
batch = FactoryGirl.create(:batch)
user = User.find(1)
status = Singleplex.new.perform(batch.id,user)
expect(status.should == true)
end
end
解決すべき問題が2つあります。
1)結果を検証する前に、delayed_job呼び出しが完了するまで待機するようにテストに指示するにはどうすればよいですか?
2)結果を検証するには、複数のテーブルの値を確認する必要があります。 Rspecでこれを行う最良の方法は何ですか?
編集
追加する必要があるのは、delayed_jobオブジェクトを取得するためです。もちろん、ステータスチェックは失敗します。ジョブは通常、少なくとも10分かかります。
1) Batch runs Singleplex for a valid panel
Failure/Error: expect(status.should == true)
expected: true
got: #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0, handler: "--- !Ruby/object:Delayed::PerformableMethod\nobject:...", last_error: nil, run_at: nil, locked_at: nil, failed_at: nil, locked_by: nil, queue: nil, created_at: nil, updated_at: nil> (using ==)
これを行うにはいくつかの方法があります。それらのすべてはあなたがあなたのコードでジョブを実行することを必要とします。
方法1:ジョブをキューに入れてから、DelayedJob::Worker
に完了を通知するテスト。
describe Batch do
it 'runs Singleplex for a valid panel' do
batch = FactoryGirl.create(:batch)
user = User.find(1)
Singleplex.new.perform(batch.id,user)
expect(Delayed::Worker.new.work_off).to eq [1, 0] # Returns [successes, failures]
# Add expectations which check multiple tables to make sure the work is done
end
end
方法2:キューを無効にして問題のジョブを実行し、目的の結果を確認するテスト。テスト構成のどこかまたはbefore
ブロックでDelayed::Worker.delay_jobs = false
を呼び出すことにより、キューイングを遅らせることができます。
before(:each) do
Delayed::Worker.delay_jobs = false
end
describe Batch do
it 'runs Singleplex for a valid panel' do
batch = FactoryGirl.create(:batch)
user = User.find(1)
Singleplex.new.perform(batch.id,user)
# expectations which check that the work is done
end
end
ただし、この方法は コールバックの問題の原因 として知られています。
方法3:作成される新しいジョブを監視して実行するオブザーバーを記述します。これにより、テストで「work_off」を手動で宣言する必要がなくなります。 Artsyには これの要点 があります。
ジョブが期待どおりにキューに入れられることを確認するテストを他の場所に置くことも良い考えです
it "queues welcome when a user is created" do
expect(Delayed::Job.count).to eq 0
# Create user step
expect(Delayed::Job.count).to eq 1 # You should really be looking for the count of a specific job.
end
単一のテストまたは一連のテストを中心に遅延ジョブを実行する場合は、これをspec_helper.rbに追加できます
config.around(:each, :run_delayed_jobs) do |example|
Delayed::Worker.delay_jobs = false
example.run
Delayed::Worker.delay_jobs = true
end
そしてそれを次のように呼び出します:
it 'runs the job', :run_delayed_jobs do
# delayed job magic
end