B Seven
B Seven

Reputation: 45941

What is a good way to run background processes in foreground for tests in Ruby?

Working with a Sinatra application, and found 3 ways to run a background process:

  1. Thread.new
  2. Process.fork
  3. 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

Answers (2)

B Seven
B Seven

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

Ben Taitelbaum
Ben Taitelbaum

Reputation: 7403

I recommend the following hybrid approach:

  1. 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.

  2. 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

Related Questions