[rspec-users] shared behav

David Chelimsky dchelimsky at gmail.com
Tue Dec 18 17:37:53 EST 2007


On Dec 18, 2007 4:30 PM, Rick DeNatale <rick.denatale at gmail.com> wrote:
> On 12/18/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> > On Dec 18, 2007 11:39 AM, Jonathan Linowes <JONATHAN at linowes.com> wrote:
> > >
> > > hi, i want to make a behavior shared between models, the examples need to
> > > create new instances etc. Is there a way to pass the model class to the
> > > shared behavior?
> >
> > We're calling these shared example groups now.
> >
> > The way to affect the state within a shared example group is to use
> > before(:each) to set an instance variable:
> >
> > shared_examples_for "models that do stuff" do
> >   before(:each) do
> >     @instance = @class.new
> >   end
> >   it "should do something" do
> >    @instance.should do_something
> >   end
> > end
> >
> > describe Foo do
> >   before(:each) do
> >     @class = Foo
> >   end
> >   it_should_behave_like "models that do stuff"
> > end
>
> So I guess this means that the before block for the shared example
> group gets executed after the example group using it.  I don't recall
> seeing this documented, although I'm sure that it is.
>
> This helps me a lot.
>
> Can you do something similar with the new nested example groups? It
> doesn't seem so.
>
> describe "Shared", :shared => true do
>
>   before(:each) do
>     @outer = @inner
>   end
>
>   it "should set @outer to @inner" do
>     @outer.should == @inner
>   end
> end
>
> describe "Sharer"  do
>   it_should_behave_like "Shared"
>
>   it "should set @outer to 1" do
>     @inner = 1
>   end
> end
>
> describe "Outer" do
>   before(:each) do
>     @outer = @inner
>   end
>
>   describe "inner one" do
>     before(:each) do
>       @inner = 1
>     end
>
>     it "should be set outer to 1" do
>       @outer.should == 1
>     end
>   end
>
>   describe "inner two" do
>     before(:each) do
>       @inner = 2
>     end
>
>     it "should be set outer to 1" do
>       @outer.should == 2
>     end
>   end
> end
>
> k$ spec ~/nestedspec.rb
> FF..
>
> 1)
> 'inner one should be set outer to 1' FAILED
> expected: 1,
>      got: nil (using ==)
> /Users/rick/nestedspec.rb:16:
>
> 2)
> 'inner two should be set outer to 1' FAILED
> expected: 2,
>      got: nil (using ==)
> /Users/rick/nestedspec.rb:26:
>
> Finished in 0.00627 seconds
>
> 4 examples, 2 failures

That's actually as it should be. The common use case for nested is
that you create something in the outer group and expand its definition
in the inner group.

describe Thing do
  before(:each) { @thing = Thing.new }

  describe "with special magic powers" do
    before(:each) { @thing.grant_special_magic_powers }
    it "should be able to conjure up world peace" do
      @thing.should be_able_to_conjure_up_world_peace
    end
  end
end

This requires running the befores in the outer groups first, which is
the opposite of what your example would require.

Make sense?

David


More information about the rspec-users mailing list