[rspec-users] Evaluating shared example customisation block before shared block

Myron Marston myron.marston at gmail.com
Sun Aug 1 12:40:19 EDT 2010

> The particular issue of simple values being used in the docstrings and the examples themselves (i.e. exposed to everything in the block scope) could be handled like this:
> shared_examples_for "blah" do |a,b|
>   ...
> end
> it_should_behave_like "blah", 1, 2

Fantastic idea.  I'm sold.  I'm not sure why this simple idea didn't
occur to me earlier :(.

> That's no different from methods that have default values for arguments:
>   def foo(bar, baz = :default)
> If you provide only 1 arg, all is well, but the first one is required. Here's the same idea expressed in a group:
> shared_examples_for "foo" do
>   unless defined?(:bar)
>     raise "you need to supply a bar() method"
>   end
>   unless defined?(:baz)
>     def baz; :default; end
>   end
> end

This does indeed work, to the extent that the methods the consumer
needs to override are ones the author of the shared example ground had
in mind, and coded as such.  This isn't an issue when the shared
example group and the consuming code are in the same code base.  But
the idea has been brought up that shared example groups could be
provided by a library for users to use to enforce a contract of some
class or object they write that the library interacts with.  I think
it's likely that library authors won't declare their helper methods
using the "unless defined?" idiom, because they can't anticipate all
the needs of their users, and they probably aren't even aware that
they have to declare their methods this way to allow them to be
overridden.  Suddenly it's _impossible_ for consumers of the shared
example group to override any of the helper methods.

I _love_ how flexible ruby is, and the fact that every method can be
overridden, without the original author of the a method having to do
anything special to allow it.  Your suggestion above seems (to me
anyway) to be more in line with a language like C#, where methods are
not overriddable by default, and developers have to use the virtual
keyword to make them so.

So, all of that is just to say that I'm still in favor of eval'ing the
customization block last.  To me, the primary need for eval'ing the
customization block first was to allow it define class helper methods
that the shared example group could use to interpolate into doc
strings, and this need is solved much more elegantly with David's
suggestion.  I like eval'ing it last so that helper methods can be
overridden, _without_ anything special being done in the shared
example group.

Of course, if there are other things that will only work by eval'ing
the block first, then I'm completely fine with it--I'm just not seeing
the need right now.


More information about the rspec-users mailing list