Reputation: 45941
Working with a Sinatra application, and found 3 ways to run a background process:
Thread.new
Process.fork
Process.spawn
Figured out how to get the first two to work, but now the challenge is that the tests need to run synchronously (for a few reasons).
What is a good way to run jobs asynchronously in production, but force the tests to run synchronously? Preferably with a call in the spec_helper
...?
Ruby 1.9.3, Sinatra app, RSpec.
Upvotes: 1
Views: 1563
Reputation: 45941
Here's what I came up with:
process_in_background { slow_method }
def process_in_background
Rails.env == 'test' ? yield : Thread.new { yield }
end
def slow_method
...code that takes a long time to run...
end
I like this solution because it is transparent: it runs the exact same code, just synchronously.
Any suggestions/problems with it? Is it necessary to manage zombies? How?
Upvotes: 0
Reputation: 7403
I recommend the following hybrid approach:
Write simple unit tests and refactor what you're testing to be synchronous. In other words, put all of the background functionality into straightforward classes and methods that can be unit tested easily. Then the background processes can call the same functionality, that's already been unit tested. You shouldn't have to unit test the background thread/process creation itself, since this is already tested in ruby (or another library like god
, bluepill
or Daemons
. This TDD approach has the added benefit of making the codebase more maintainable.
For functional and integration tests, follow the approach of delayed_job
and provide a method to do all of the background work synchronously, like with Delayed::Worker.new.work_off
You also may want to consider using EventMachine (as in Any success with Sinatra working together with EventMachine WebSockets? ) over spawning threads or processes, especially if the background processes are IO intensive (making http or database requests, for example).
Upvotes: 2