web-dev-qa-db-ja.com

Rspecテストdelay_job

私のアプリケーションには、複雑で長時間実行される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 ==)
25
ardochhigh

これを行うにはいくつかの方法があります。それらのすべてはあなたがあなたのコードでジョブを実行することを必要とします。

方法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
37
fny

単一のテストまたは一連のテストを中心に遅延ジョブを実行する場合は、これを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
8
stevenspiel