ExampleGroup and SharedExampleGroup relationship(?)

I’m working on a series going over the source code for rspec, and I ran
into
something interesting with ExampleGroup and SharedExampleGroup. I was
wondering if anyone could shed light on it.
[NOTE: I’m working through the code for my own edification in learning
Ruby.
Ruby has some features that I think are incredibly cool, so I’m using a
concrete implementation (RSpec) as a learning tool to see them
implemented.
Along the way, I figured I would ask questions that were confusing to
me.
So, please bear with me and please please please do not take this as
criticisms/attacks]

I expected to see SharedExampleGroup < ExampleGroup, but, instead, I saw
SharedExampleGroup < Module. This is incredibly confusing to me. I
realize
that they don’t even need to have any relationship to each other since
they
get their shared functionality through the module ExampleGroupMethods,
but
it still seems a bit odd to me that they don’t have a hierarchical
relationship.

If there is some hidden meaning, I’d love to hear it. I’ll post it as an
update to the blog entry, too.

Oh, and here are the links to the first few parts of the series if
anyone is
interested: It looks like I’ll be able to get about a post a week on it.

part 1:
http://www.coreyhaines.com/coreysramblings/2007/12/15/ARubyNewbieLooksThroughRSpecPartIWhatIsThis.aspx

part 2:
http://www.coreyhaines.com/coreysramblings/2007/12/15/ARubyNewbieLooksThroughRSpecPartIIDescribe.aspx

part 3:
http://www.coreyhaines.com/coreysramblings/2007/12/22/ARubyNewbieLooksThroughRSpecPartIIIDescribeRedux.aspx
part 4: I’m working on this, which is where I noticed the
ExampleGroup/SharedExampleGroup thing.

-Corey

On Dec 27, 2007, at 11:30 AM, Corey H. wrote:

I expected to see SharedExampleGroup < ExampleGroup, but, instead,
I saw SharedExampleGroup < Module. This is incredibly confusing to
me. I realize that they don’t even need to have any relationship to
each other since they get their shared functionality through the
module ExampleGroupMethods, but it still seems a bit odd to me that
they don’t

Yep - it certainly was surprising to me too. Here’s some explanation
(although not on the design decision front - just on the Ruby, how it
works front):

When you use the keyword module, you are actually creating a new
instance of the Module class. So these two are equivalent:

MyMod = Module.new()

module MyMod; end

So - Module is a class, but a module is a module (i.e., an instance
of the class Module).

The SharedExampleGroup is a class, which decends from the Module
class. This, in effect, makes a new SharedExampleGroup instance act
like a typical module (it is a kind_of?(Module)) - just as if you had
declared it with Module.new or the keyword.

The advantage of using the approach of instantiating over using the
keyword is that the keyword always requires a constant to be defined

  • on the other hand, Module.new doesn’t need a constant, and can be
    passed around as a regular object without needing to define these
    constants on the fly.

Since the SharedExampleGroup is a subclass of Module, the instances
of SharedExampleGroup can be included just as a regular module can
be, into the regular old ExampleGroup (this is what happens when you
say it_should_behave_like “…” - the instances methods of the
SharedExampleGroup are copied directly.

Now - for why it was implemented this way, and not another way, David
or Aslak could tell you much better than I.

Also - it’s likely this implementation will change in the near future.

Hope that helps.

Scott

On Dec 27, 2007 8:30 AM, Corey H. [email protected] wrote:

I expected to see SharedExampleGroup < ExampleGroup, but, instead, I saw
SharedExampleGroup < Module. This is incredibly confusing to me. I realize
that they don’t even need to have any relationship to each other since they
get their shared functionality through the module ExampleGroupMethods, but
it still seems a bit odd to me that they don’t have a hierarchical
relationship.

Whenever you write an example, RSpec defines a method. Shared example
groups are basically sugary modules. They define examples - methods -
that get included into your “real” example groups.

I can’t say for sure if there’s any deeper meaning to it other than
it’s the simplest implementation. It would be possible to make
SharedExampleGroup be a class, but then when an ExampleGroup uses
it_should_behave_like, it would have to list all the examples in the
SharedExampleGroup, define methods on itself that delegate to the
SEG…as opposed to just mixing in a module :slight_smile:

I admit I’m pulling all of this out of my ass, btw, but I think it’s
right. I’m sure David will clarify soon.

Pat

On Dec 27, 2007 11:12 AM, Scott T. [email protected]
wrote:

On Dec 27, 2007, at 11:30 AM, Corey H. wrote:
I’m working on a series going over the source code for rspec, and I ran into
something interesting with ExampleGroup and SharedExampleGroup. I was
wondering if anyone could shed light on it.

Now - for why it was implemented this way, and not another way, David or
Aslak could tell you much better than I.

Also - it’s likely this implementation will change in the near future.

I had said it might change a while back, but at this point we are
quite happy with the way this works and don’t expect it to change.

The reason we like it is as you described: to use a shared group you
just include the module and you get everything for free. The
alternative is slinging around a bunch of Method objects. This would
be fine if it added some value, but the way things have landed it
really doesn’t.

Cheers,
David

Thanks to both Pat and Scott for the first two comments. I’m digesting
what
you are saying. I’ll take these ideas (and any others that come) and try
to
summarize them in and upcoming post.

Thanks.
-Corey

On Dec 27, 2007 11:21 AM, Pat M. [email protected] wrote:

that get included into your “real” example groups.

I can’t say for sure if there’s any deeper meaning to it other than
it’s the simplest implementation.

That’s about right.

Cheers,
David