使用capybara-webkit的不稳定的Sidekiq工作行为

时间:2016-01-25 10:41:13

标签: ruby-on-rails-4 selenium-webdriver capybara sidekiq capybara-webkit

我正在维护一套功能规范,其中包含许多在测试中运行的sidekiq作业。一切都很好,直到需要为所有功能规格启用javascript,事情突然变得丑陋。我不确定我理解的原因。

典型问题如下: 在spec的开头,我调用了helper,最终启动了Sidekiq的工作:

it 'does something fancy' do
  Sidekiq::Testing.inline! do
    page.attach_file('black_list_file', file)
    click_on 'Import file'
  end

  expect(page).to have_content('Import started') # No problem here
  expect(page).to have_link('imported_file.csv') # This fails
end

我尝试将sleep n放在expect语句之间 - 即使n = 10也没有运气。然后我尝试调试,并注意到一些奇怪的事情:ImportWorker.jobs返回仍在队列中的作业,如果我从调试器中明确说明ImportWorker.drain,则spec将通过。

但是!如果我将ImportWorker.drain放在expect行之间 - 它仍然会失败,即使我在排除之前放置sleep,也要等待请求实际调用worker perform_async

当我切换到selenium驱动程序时,事情变得更加奇怪 - 一切顺利,测试通过。

现在,我已经了解了如何根据规范在不同的线程中处理来自水豚的请求,如here所述。因此,可能在调用worker时,它不知道inline!,只是将作业放入Redis队列。我仍然不明白为什么Selenium能够管理这个问题。如果这是真的,我如何使用webkit驱动程序测试涉及sidekiq作业的功能。

UPD。

好的,正如我预期的那样Sidekiq::Testing.inline?在调用worker的地方返回false,即使请求是从inline!阻止的。

这解决了所有问题:

if Rails.env.test?
  Sidekiq::Testing.inline! do
    ImportWorker.perform_async(args)
  end
else
  ImportWorker.perform_async(args)
end

显然,这与最佳实践尽可能远,所以我正在考虑编写一个类,它将接受工作者名称作为字符串或符号,并在有或没有inline!的情况下对其执行调用阻止取决于环境。这样我就可以在一个地方保持这种丑陋,而不需要污染控制器和模型。

如果您认为这是一个糟糕的解决方案,请发表评论。

1 个答案:

答案 0 :(得分:2)

所有Sidekiq :: Testing.inline! (在传递块时)在执行块之前设置全局(非线程特定)设置,然后在块完成时重置该设置。我相信您的测试失败的原因是,即使您单击块内的按钮/链接,在设置全局内联设置时,作业实际上也不会被添加到队列中。这是因为#click_on在点击后立即返回,并且不需要等待该点击的任何副作用(表单提交,JS行为等)。如果你移动你的期望(等待副作用发生)在块内,那么测试应该通过。

it 'does something fancy' do
  Sidekiq::Testing.inline! do
    page.attach_file('black_list_file', file)
    click_on 'Import file'

    expect(page).to have_content('Import started') # No problem here
    expect(page).to have_link('imported_file.csv') 
  end
end

另一种选择是使用RSpec around块来根据测试中设置的元数据更改Sidekiq测试设置 - 在RSpec配置中添加如下内容(注意:未尝试)

RSpec.configure do |config|
 config.around(:example, :sidekiq_inline) do |example|
   Sidekiq::Testing.inline! do
     example.run
   end
  end
end   

然后应该让你做

it 'does something fancy', :sidekiq_inline do
  page.attach_file('black_list_file', file)
  click_on 'Import file'

  expect(page).to have_content('Import started') # No problem here
  expect(page).to have_link('imported_file.csv') 
end

您还可以添加清除sidekiq队列等内容到周围的区域。