Подтвердить что ты не робот

Проверка Rspec delayed_job

В моем приложении есть сложные, длительные процессы delayed_job. Я использую Rspec для проверки отдельных методов и классов, используемых в процессах, но я также хотел бы выполнить множество сквозных фоновых заданий с различными тестовыми данными.

Я ничего не мог найти в вики-странице delayed_job, и этот вопрос SO выглядит интересным, но я действительно не понял, что здесь происходит. Каков наилучший способ тестирования цепочек delayed_job с помощью rSpec?

Я могу легко настроить тестовые данные с помощью factory, а затем вызвать класс, который запускает фоновую обработку. Я ожидаю, что тесты пройдут много времени.

отредактированный код фона

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 }

спецификации/фабрики/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

У меня есть две проблемы:

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 ==)
4b9b3361

Ответ 1

Есть несколько способов сделать это. Все они требуют выполнения задания в вашем коде.

Метод 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: Тест, который запускает задание, о котором идет речь, с отключенной очередью и проверяет желаемые результаты. Вы можете отложить очередь, вызывая Delayed::Worker.delay_jobs = false где-то в вашей конфигурации тестирования или в блоке 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

Этот метод, однако, известен вызывает проблемы с обратными вызовами.

Способ 3: Напишите наблюдателя, который следит за любыми новыми заданиями, которые создаются и запускают их. Таким образом, вам не придется вручную объявлять "work_off" в своих тестах. Для этого в Arty есть .

Также неплохо иметь тесты в другом месте, которые гарантируют, что задания будут поставлены в очередь, как ожидалось

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

Ответ 2

Если вы хотите запустить замедленную работу вокруг одного теста или набора тестов, вы можете добавить это в свой 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