[rspec-users] Module & Mixin testing strategy

David Chelimsky dchelimsky at gmail.com
Sat Aug 14 10:53:32 EDT 2010


On Aug 14, 2010, at 9:26 AM, Ashley Moran wrote:

> 
> On 14 Aug 2010, at 11:34, Mike Howson wrote:
> 
>> Just wondered what people thoughts are to testing module's to be
>> included in mixin's? Seems to me there are two main approaches:-
> 
> Hi Mike
> 
> I've been doing a lot of this sort of coding lately, as I've been extracting duplicated code into a mini-framework based on modules.
> 
> 
>> 1. Test the behavior in a mixin object that includes the module because
>> its the behavior of the object thats important not the code structure.
>> 
>> 2. Test the module in isolation as it potentially code be included
>> anywhere.
> 
> I'm not sure I know how option 2 is even possible, unless your module is all module methods, as you can't call instance methods on a module directly.
> 
> However, it's easy to do this in RSpec with some Ruby meta-magic:
> 
>  module MyModule
>    def foo
>      "bar"
>    end
>  end
> 
>  describe MyModule do
>    let(:class_with_my_module) {
>      Class.new do
>        include MyModule
>      end
>    }
> 
>    subject { class_with_my_module.new }
> 
>    its(:foo) { should eq bar }
>  end

Or:

describe M do
  it "does something" do
    host = Object.new.extend(M)
    host.some_method_defined_in_m.should do_something
  end
end

I think either approach satisfies "test the module in isolation", even though it's not in isolation from the behaviour of Object.

> If the best approach is 2 - to test the module in isolation and the
>> module uses instance variables or methods from the object its being
>> mixed with then we would need to create a test object in the rspec test
>> that included the module and defined the required instance variables and
>> methods. Does this lead to 1 being the best approach as we are not then
>> forced to mock up a mixin just to test the module?
> 
> I'm not 100% sure but I *think* the snippet above is an implementation of what you describe here.  Please correct me if I misunderstood.
> 
> 
>> The question came about because I recently had to get an untested rails
>> module under test that was included in a number of controllers and
>> depended on 'request' and 'response'. I was then faced with either
>> testing one of the controllers that included that module but also added
>> further complexity or defining a new thin controller used solely for
>> testing the module within the spec file.
> 
> In this case, you may be able to get some mileage with the above code, but using `Class.new(ActionController::Base)`.
> 
> You can test individual objects that include your module with shared examples, for example:
> 
>  module Fooable
>    def foo
>      "bar"
>    end
>  end
> 
>  class Baz
>    include Fooable
> 
>    # Oops - this is overriding Fooable#foo
>    def foo
>      "quux"
>    end
>  end
> 
>  shared_examples_for "a Fooable object" do
>    # Optional
>    before(:each) do
>      unless respond_to?(:fooable)
>        raise "You must provide instance method fooable"
>      end
>    end
> 
>    it "should have a foo of 'bar'" do
>      fooable.foo.should eq "bar"
>    end
>  end
> 
>  describe Baz do
>    subject { Baz.new }
>    it_should_behave_like "a Fooable object" do
>      let(:fooable) { subject }
>    end
>  end
> 
> My recommendation at the moment is to make the shared examples work fully-integrated (ie, no mocks).  I've run into issue where shared examples rely on mocks, which I haven't solved yet (at least not in my code - it's my next TODO).
> 
> Currently I'm doing both the above.  The isolated module spec proves the module enchants objects with the correct behaviour, the shared examples double-check that you haven't broken that behaviour in concrete classes.
> 
> See also the recent thread "Evaluating shared example customisation block before shared block" from 30th July onwards (it goes on to talk about passing parameters to shared example groups, which is possible in RSpec-2 master).
> 
> HTH
> 
> Ash
> 
> -- 
> http://www.patchspace.co.uk/
> http://www.linkedin.com/in/ashleymoran
> 
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



More information about the rspec-users mailing list