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@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users