[rspec-users] shared behav

David Chelimsky dchelimsky at gmail.com
Tue Dec 18 17:47:15 EST 2007


On Dec 18, 2007 4:45 PM, Scott Taylor <mailing_lists at railsnewbie.com> wrote:
>
>
> On Dec 18, 2007, at 5:31 PM, David Chelimsky wrote:
>
> > On Dec 18, 2007 4:25 PM, David Chelimsky <dchelimsky at gmail.com> wrote:
> >>
> >> On Dec 18, 2007 4:22 PM, Scott Taylor
> >> <mailing_lists at railsnewbie.com> wrote:
> >>>
> >>>
> >>> 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?
> >>
> >> Copying instance variables around is nasty business. In fact, we
> >> eliminated that from shared behaviours by making them modules that
> >> get
> >> included! So I would view that as a step backwards from an
> >> implementation standpoint, and it still feels like voodoo from a
> >> usability standpoint.
> >
> > Well - THAT was nothing but negative.
> >
> > Let me add some positive to balance things:
> >
> > As I think about it, I'm more inclined to make this a completely
> > different method, as I suggested as an option earlier. Something that
> > says "run in another scope with these variables." That way there's no
> > magic and consequently no confusion.
>
> I'm with you on that one.  I don't like "it_should_behave_like" much
> anyway - I end up aliasing it in a few different forms:
>
> it_should_behave_like_a
> it_should_behave_like_the
>
> and so on.
>
> Anyway - how do the nested behaviours work right now?  Are instance
> variables being copied?  Methods?

They are subclasses!!!! It's pretty sweet. We can thank Brian (and
Aslak, too) for getting us there.

Basically there is no copying, just inheriting or, in the case of
shared, mixing in. Ruby does the rest for free.

>
>
> Scott
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list