RSpec and Rcov are not playing nice

14 Feb 2007

So I ran into this weird problem with RSpec (the unit test (spec) framework for Ruby) and Rcov (a code coverage tool also for Ruby). At some point, usually as your list of specs gets longer, if you run your specs with Rcov they blow up with a seg fault. I’ve seen this happen on OSX, Windows, and now Linux. On my last project we just had to give up running Rcov (which sucked). This time Ricky Lui and Peter Ryan managed to figure out that if they comment out the tests that have an Active Record object mocked out for new, then Rcov is fine. Say you have an object called User and your controller gets a new instance and does a bunch of stuff to it. Well, you want to test (specify) what happens to that object so you do this:

specify “something important should happen to User” do
mock_user = mock(“mock_user”)
User.should_receive(:new).and_return(mock_user)
mock_user.should_receive(:some_method).twice.and_return(“whatever”)
etc.
end

But Rcov no like this. So to get around this bug I had to open up my object in the spec and overwrite new, like so:

class User
def self.new
@@mock
end

def self.set_mock mock
@@mock = mock
end
end

So now I can make a call to User.set_mock and give it the mock I want new to return. Not quite as elegant as the mocking framework (and it doesn’t check to make sure new is called), but it works. But here’s the weird part: I can do some mocking of new in the spec, just not too much. In the spec that was making rcov bomb, I had 7 places where it read User.should_receive(:new). If I commented out 2, the spec ran fine with rcov. If I left all 7 in, it blew up. Weird, huh?

I need to get a small version of this consistently failing so I can give it to David Chelimsky, my friend and an a RSpec admin. I want to submit the bug to Rcov, but I can’t seem to find where to submit it. I guess I’ll just email whoever’s maintaining it.