2014-10-26 6 views
21

Ich habe einige komplexe, lang laufende Prozesse delayed_job in meiner Anwendung. Ich verwende Rspec, um einzelne Methoden und Klassen zu testen, die in den Prozessen verwendet werden, aber ich möchte auch viele End-to-End-Hintergrundjobs mit unterschiedlichen Testdaten durchführen.Rspec testing delayed_job

Ich konnte nichts über das delayed_job-Wiki hier finden, und diese SO-Frage sieht interessant aus, aber ich habe nicht wirklich verstanden, was hier passiert. What's the best way to test delayed_job chains with rSpec?

Ich kann einfach die Testdaten mit einer Fabrik einrichten und dann die Klasse aufrufen, die die Hintergrundverarbeitung startet. Ich erwarte, dass die Tests sehr lange dauern.

bearbeitet Hintergrund Code

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/Fabriken/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 

Dann führen Sie den Test wie dieser

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 

Ich habe zwei Probleme zu lösen:

1) Wie kann der Test angewiesen werden, zu warten, bis der Aufruf "delayed_job" abgeschlossen ist, bevor die Ergebnisse validiert werden?

2) Um die Ergebnisse zu validieren, müssen die Werte in mehreren Tabellen überprüft werden. Was ist der beste Weg, dies in Rspec zu tun?

EDIT

ich hinzufügen sollte ich ein delayed_job Objekt zu erhalten, so natürlich nicht die Statusprüfung. Die Arbeiten dauern in der Regel mindestens 10 Minuten.

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 ==) 
+2

By the way, es sieht aus wie Sie RSpec des 'should' und' expect' Syntax abmischen. 'expect (status.should == true)' sollte entweder 'status.should == true' oder' expect (status) .to == true' sein. – fny

Antwort

31

Es gibt ein paar Möglichkeiten, dies zu tun. Für alle muss der Job in Ihrem Code ausgeführt werden.

Methode 1: Ein Test, der den Auftrag in die Warteschlange stellt und dann die DelayedJob::Worker anweist, ihn abzuschließen.

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 

Methode 2: Ein Test, der den fraglichen Job mit deaktivierter Warteschlange ausführt und nach den gewünschten Ergebnissen sucht. Sie können die Warteschlangenbildung verzögern, indem Sie in Ihrer Testkonfiguration oder in einem before Block Delayed::Worker.delay_jobs = false aufrufen.

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 

Diese Methode ist jedoch cause issues with callbacks bekannt.

Methode 3: Schreiben Sie einen Beobachter, der nach neu erstellten Jobs sucht und diese ausführt. Auf diese Weise müssen Sie "work_off" in Ihren Tests nicht manuell deklarieren. Artsy hat eine gist for this.

Es ist auch eine gute Idee, Tests an anderer Stelle zu haben, die sicher Arbeitsplätze machen lassen als

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 
+0

Danke @faraz, für Methode 3, wo hast du die Referenzen hinzugefügt 'delayed_job_observer.rb', ist es in' spec_helper.rb'? – Dean

+0

Verwenden Sie 'rails_helper.rb', wenn Sie das neuere Organisationsformat verwenden, andernfalls funktioniert' spec_helper.rb'. – fny

+0

in Ihrer ersten Methode, sollte nicht der Job sofort ausgeführt werden, wird es nicht richtig? – jshah

5

erwartet Warteschlange Wenn Sie verzögert Job um einzelnen Test oder eine Reihe von Tests durchführen, können Sie dies in dem Ihr spec_helper.rb

config.around(:each, :run_delayed_jobs) do |example| 
    Delayed::Worker.delay_jobs = false 

    example.run 

    Delayed::Worker.delay_jobs = true 
end 

Und nennen Sie es mit:

it 'runs the job', :run_delayed_jobs do 
    # delayed job magic 
end