Rob Sanheim
2007-Sep-05 19:32 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
I''m writing quite a few specs lately that use Ruby''s
Timeout::timeout
functionality, making sure that timeout errors are properly handled
and everything flows right when some command line tools timeout. I
like being able to use Mocha''s #returns right now to force a method to
raise a TimeoutError, but I know that usage is going away at some
point. I''d like to throw out the code and see if anyone has a better
way to test this with Mocha (or otherwise).
Here is some simplified code showing the example:
class FileSpace < ActiveRecord::Base
def dsmc
# remove command line wrapper object - this is basically a call
that _could_ stall out
end
def self.query_backup_timeout
15.seconds
end
# query backup may hang things, so we have to wrap it in a timeout
def query_backup_from_tsm
Timeout::timeout(self.class.query_backup_timeout) do
dsmc.parse_query_backup(dsmc.query_backup)
end
end
end
the corresponding spec:
describe "File Space" do
it "should raise a time out error if query backup takes too long" do
FileSpace.expects(:query_backup_timeout).returns(0.1) # make
timeout very short
file_space = FileSpace.new
# force the parse_query_backup method to sleep for 10 seconds,
therefore making the timeout happen
file_space.dsmc.expects(:parse_query_backup).returns(lambda{ sleep(10) } )
e = lambda { file_space.query_backup_from_tsm }.should.raise(Timeout::Error)
end
end
Again, this is the simplest case -- in more complex examples I have
specs making sure that the timeout error is logged, and that the error
state gets saved to the database accordingly in the rescue clause. In
other cases we used modules in our tests to override the real
implementation in the singleton class (by doing
dsmc.extend(TimeoutModule) for example), but thats a bit ugly and
tiresome.
Does anyone see a better way to do this? I really just want to say "I
don''t care what this method normally does, just pretend that in this
spec it takes n seconds long to complete to force a TimeoutError.
thanks,
Rob
--
http://robsanheim.com
Duncan Beevers
2007-Sep-05 22:03 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
Would it be acceptable to just have the potentially long-running method raise the Timeout::Error itself and allow the error to percolate up out of Timeout::timeout? file_space.dsmc.expects(:query_backup).raises(Timeout::Error, ''took too long'')
James Mead
2008-Mar-28 16:13 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
I just found this old reply sitting in my drafts folder. I don''t know if it''s any use, but... Hmm. I don''t like having multiple threads knocking around in my unit tests> (see http://www.jmock.org/threads.html - although its examples are in > Java, don''t be put off - they are very readable). > > In this case you are really testing two things - firstly that you are > wrapping the call with a timeout and secondly that the timeout is working > correctly. I would suggest that the second issue is testing third party code > that you should be able to rely on (and ideally should have its own tests). > So in order to test the first issue, you could set up an expectation for the > call to Timeout::timeout. Unfortunately there isn''t currently a nice way to > check that you are passing in the correct block to the timeout method. > > I''m going to mention this to James Adam (one of the other developers at > Reevoo) who ran into a similar issue a while ago - he might be able to help. > -- > James. > http://blog.floehopper.org > http://tumble.floehopper.org >