Prueba de Rspec con retraso en el trabajo
delayed-job (2)
Tengo algunos procesos complejos de larga duración en mi aplicación. Estoy usando Rspec para probar métodos y clases individuales utilizados en los procesos, pero también me gustaría realizar muchos trabajos de fondo de extremo a extremo, con diferentes datos de prueba.
No pude encontrar nada en la wiki de retraso en el trabajo sobre esto, y esta pregunta SO parece interesante, pero realmente no entendí lo que está sucediendo aquí. ¿Cuál es la mejor manera de probar las cadenas retrayed_job con rSpec?
Puedo configurar fácilmente los datos de prueba con una fábrica y luego llamar a la clase que inicia el procesamiento en segundo plano. Espero que las pruebas tarden mucho en completarse.
código de fondo editado
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
Luego ejecuta la prueba de esta manera
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
Tengo dos problemas para resolver:
1) ¿Cómo se le dice a la prueba que espere hasta que se complete la llamada a la operación demorada antes de validar los resultados?
2) Para validar los resultados, tendré que verificar los valores en múltiples tablas. ¿Cuál es la mejor manera de hacer esto en Rspec?
EDITAR
Debo añadir que recibo un objeto de retraso de trabajo, por lo que, por supuesto, la comprobación de estado falla. Los trabajos toman al menos 10 minutos por lo general.
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 ==)
Hay algunas maneras de hacer esto. Todos ellos requieren que ejecutes el trabajo en tu código.
Método 1: una prueba que DelayedJob::Worker
cola el trabajo y luego le dice a DelayedJob::Worker
que lo complete.
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
Método 2: una prueba que ejecuta el trabajo en cuestión con cola desactivada y comprueba los resultados deseados. Puede demorar la cola llamando a Delayed::Worker.delay_jobs = false
en algún lugar de la configuración de prueba o en un bloque before
.
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
Sin embargo, se sabe que este método causa problemas con las devoluciones de llamada .
Método 3: escriba un observador que observe los trabajos nuevos que se creen y los ejecute. De esta forma, no tendrá que declarar manualmente "work_off" en sus pruebas. Artsy tiene una esencia para esto .
También es una buena idea tener pruebas en otros lugares que aseguren que los trabajos se pongan en cola como se esperaba
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
Si desea ejecutar un trabajo retrasado en una sola prueba o un conjunto de pruebas, puede agregar esto a su spec_helper.rb
config.around(:each, :run_delayed_jobs) do |example|
Delayed::Worker.delay_jobs = false
example.run
Delayed::Worker.delay_jobs = true
end
Y llámalo con:
it ''runs the job'', :run_delayed_jobs do
# delayed job magic
end