4

I'm writing a delayed_job clone for DataMapper. I've got what I think is working and tested code except for the thread in the worker process. I looked to delayed_job for how to test this but there are now tests for that portion of the code. Below is the code I need to test. ideas? (I'm using rspec BTW)

def start
  say "*** Starting job worker #{@name}"
  t = Thread.new do
    loop do
      delay = Update.work_off(self) #this method well tested
      break if $exit
      sleep delay
      break if $exit
    end
    clear_locks
  end

  trap('TERM') { terminate_with t }
  trap('INT')  { terminate_with t }

  trap('USR1') do
    say "Wakeup Signal Caught"
    t.run
  end

see also this thread

1
  • "see also this thread" - was that pun intentional? Commented Jul 1, 2011 at 10:41

4 Answers 4

11

The best approach, I believe, is to stub the Thread.new method, and make sure that any "complicated" stuff is in it's own method which can be tested individually. Thus you would have something like this:

class Foo
    def start
        Thread.new do
            do_something
        end
    end
    def do_something
        loop do
           foo.bar(bar.foo)
        end
    end
end

Then you would test like this:

describe Foo
    it "starts thread running do_something" do
        f = Foo.new
        expect(Thread).to receive(:new).and_yield
        expect(f).to receive(:do_something)
        f.start
    end
    it "do_something loops with and calls foo.bar with bar.foo" do
        f = Foo.new
        expect(f).to receive(:loop).and_yield #for multiple yields: receive(:loop).and_yield.and_yield.and_yield... 
        expect(foo).to receive(:bar).with(bar.foo)
        f.do_something
    end
end

This way you don't have to hax around so much to get the desired result.

Sign up to request clarification or add additional context in comments.

Comments

3

You could start the worker as a subprocess when testing, waiting for it to fully start, and then check the output / send signals to it.

I suspect you can pick up quite a few concrete testing ideas in this area from the Unicorn project.

Comments

0

Its impossible to test threads completely. Best you can do is to use mocks.

(something like) object.should_recieve(:trap).with('TERM').and yield object.start

Comments

0

How about just having the thread yield right in your test.

Thread.stub(:new).and_yield
start
# assertions...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.