Let's say that we have a Ruby object with some class methods. In my case, we want to be able to inject a driver at the class level that all instances will use:
[code language='ruby'] class Mod::Thingy def self.driver end def self.driver=(d) end end
And let's say that .driver has a default value. So the class looks more like this:
[code language='ruby'] class Mod::Thingy def self.driver @driver || DefaultDriver end def self.driver=(d) @driver = d end end
Now here's the dealio. Let's say that we test for the default value first. So we check Mod::Thingy.driver == DefaultDriver
. Then we test the setter. We do Mod::Thingy.driver = OtherDriver
, and then check the return value of Mod::Thingy.driver
. Fair enough.
But what if we ran the examples in reverse? Now we do Mod::Thingy.driver = OtherDriver
first, check it; but now in our second test, we can't test the default value, because the state of Mod::Thingy
has been changed.
Strategies:
around
feature to save the state of Mod::Thingy.driver
and restore it afterwards. What I don't like about this is that now the around method has to know all about all of the setters at the class level. Meanwhile, it is possible to imagine objects that are difficult to set back to their default state: Perhaps the class methods have order dependencies themselves. This would make the test need to know a lot about the inner state of the object..reset!
method on the object. But this seems a bit nutty: Add a method just to make testing easier?before(:each)
block:[code language='ruby'] Mod.send(:remove_const, 'Thingy') load "#{PROJECT_ROOT}/lib/mod/thingy.rb"
Now we're getting a nice clean class. To me, (3) is more parallel to the testing convention of new'ing up an object instance for the test.
Thoughts?
comments powered by Disqus