[rspec-users] shared behav

Scott Taylor mailing_lists at railsnewbie.com
Tue Dec 18 17:22:46 EST 2007


On Dec 18, 2007, at 5:12 PM, David Chelimsky wrote:

> On Dec 18, 2007 3:53 PM, Scott Taylor  
> <mailing_lists at railsnewbie.com> wrote:
>>
>>
>> On Dec 18, 2007, at 4:42 PM, David Chelimsky wrote:
>>
>>> On Dec 18, 2007 3:37 PM, Scott Taylor
>>> <mailing_lists at railsnewbie.com> wrote:
>>>> The
>>>> shared behaviours can be thought of modules which are included
>>>> into the
>>>> current behaviour - so it should also have access to any methods
>>>> defined in
>>>> the example (group) in which it is shared.
>>>
>>> You don't even have to think of it that way - that's actually what
>>> they are - modules that get included. You can actually assign  
>>> them to
>>> a constant and just use Ruby include.
>>
>> Although we've talked about the implementation changing, which would
>> cause those who use them as modules to have broken specs.
>
> It would, but we stopped talking about it :)
>
> It actually works quite well this way. The change came up, iirc, in
> the conversation about parameterizing it_should_behave_like, right?
> I've got a solution for that worked out, but I haven't applied it yet
> because I want to discuss it a bit:
>
> You'd use it like this:
>
> shared_examples_for "anything" do
>   it "should do stuff" do
>     @thing.should do_stuff
>   end
> end
>
> describe SpecificThing do
>   it_should_behave_like "anything", :thing => SpecificThing.new
> end
>
> Now comes the tricky part. This can work one of two ways. In either
> case it turns :thing into an instance variable @thing. The question is
> whether that instance variable is assigned in the scope of the
> SpecificThing example group or in a scope created especially to run
> the shared examples. Each choice presents usability confusion in my
> view.
>
> Imagine this scenario:
>
> shared_examples_for "anything" do
>   it "should do stuff" do
>     @thing.should do_stuff
>   end
>   it "should be like another thing" do
>     @thing.should be_like(@other_thing)
>   end
> end
>
> describe SpecificThing do
>   before(:each) do
>     @thing = SpecificThing.new
>   end
>   it_should_behave_like "anything", :other_thing => SpecificThing.new
>
>   it "should not be unlike other thing" do
>     @thing.should_not be_unlike(@other_thing)
>   end
> end
>
> If @other_thing is defined in the context of a separate scope just to
> run the shared examples, the shared examples won't know about @thing.
>
> If @other_thing in the scope of the example group created by "describe
> SpecificThing," then it's just confusing to look at - both
> before(:each) and it_should_behave_like are creating instance
> variables in the current scope, and it is NOT clear that is what is
> happening.
>
> If we go w/ the separate scope, then the metaphor of
> it_should_behave_like is wrong, because we're not talking about
> something in the current scope that should behave like something else
> anymore. We'd probably want a different construct to create these,
> even though the underlying mechanism would be the same.
>
> Thoughts?


How about this:

Use a separate scope, but copy the instance variables from the  
calling example group.  Any parameters passed into the shared example  
group will be methods which wrap the values given.   This way we  
don't have instance variable naming conflicts (like @other_thing, in  
the example above).

On the other hand, this would also mean that shared example groups  
wouldn't have the ability to call methods in the calling example group.

Thoughts?

Scott



More information about the rspec-users mailing list