Specifying mixins

Hi folks,

Can anyone share some accumulated wisdom about the best way to spec
mixins in general, and (Jamis B.-style) ActiveRecord “concerns” in
particular?

The standard situation here is that there’s a bunch of functionality,
related by concept if not by implementation, that one wants to inherit
in many different classes (e.g. ActiveRecord models) without having to
actually use subclassing – straightforward enough. But since BDD best
practice encourages one expectation per example and no mocking in the
behaviour setup, the specification for this shared functionality is
often spread across many behaviours, each of which may need to do its
own setup and teardown.

So, how best to mix the mixin spec in with the spec for each class
that uses the mixin (IYSWIM)? I’ve tried several permutations of
helpers, spec mixins, shared-shared behaviours and so on, but can’t
find anything which is persuasively neat and DRY while still working
reliably. One point of contention is that the mixin’s behaviours might
need to do things like instantiate the target class with specific
arguments in before :each (or call some other class method, if the
mixin provides some) so it’s not really good enough for the target
spec to just squirrel away a prebuilt object in an instance variable.

Any advice, please?

Cheers,
-Tom

just a short advice:

describe MyModule do
it “should do something” do
# The module is automatically mixed into your spec
end
end

Aslak

On Nov 1, 2007, at 7:30 PM, aslak hellesoy wrote:

just a short advice:

describe MyModule do
it “should do something” do
# The module is automatically mixed into your spec
end
end

Aslak

I suppose it really depends on how static/dynamic the module is.
This seems to work well for a relatively static case, but how you
spec out a module like Enumerable in this manner (in which a series
of methods is added to class if a method is implemented in the class

  • in the case, #each)?

Scott

On 6 Nov 2007, at 02:00, Jim L. wrote:

Add an additional describe block for the class that you’re including
the module into, and then setup a genericly named object in the before
block
[…]

page_spec.rb

describe Page, “should include publishing features” do
include PublishableSpec

before(:each) do
@model = Page.new(:title => “title”, :content => “content”,
:published => false)
end

Yeah, this is fine for a simple mixin with only one shared behaviour,
but the problem is that a real chunk of mixed-in functionality will
probably need many behaviours that correspond to different initial
states (provided you’re behaving yourself and not doing too much state
setup within the individual examples).

So, firstly, perhaps I’ll have ten shared behaviours to specify my
mixin – do I have ten calls to it_should_behave_like in the spec for
each target class?

And secondly, perhaps each of those shared behaviours is talking about
an object with different initial state, e.g. constructed with
different arguments (a published thing, an unpublished thing, a
published but deleted thing) – how do I arrange for that to happen?
Ten corresponding behaviours each containing the appropriate
before(:each) and a call to it_should_behave_like? Or arrange for the
shared behaviours to somehow do the initialisation themselves, e.g. by
doing some kind of parameterized helper gymnastics where you pass in
the child class object and the shared behaviour calls #new on it?

None of this is impossible to do, it’s just that it all feels very
repetitious and difficult in contrast to the elegant solutions that
people often post here. I’m hoping that this sort of “okay, you
understand the basics, but NOW what?” issue is the kind of thing that
the hotly-anticipated RSpec book will address, because any information
about best practice in this area is really lacking, but I fear it
might not be that kind of book!

Cheers,
-Tom

I suppose it really depends on how static/dynamic the module is.
Add an additional describe block for the class that you’re including
the module into, and then setup a genericly named object in the before
block and then include the shared behaviours from the module’s spec
module. Like this:

page_spec.rb

describe Page, “should include publishing features” do
include PublishableSpec

before(:each) do
@model = Page.new(:title => “title”, :content => “content”,
:published => false)
end

it_should_behave_like “Publishable” # include the shared tests
end

post_spec.rb

describe Post, “should include publishing features” do
include PublishableSpec

before(:each) do
@model = Post.new(:title => “title”, :content => “content”,
:published => false)
end

it_should_behave_like “Publishable” # include the shared spec
end

publishable_spec.rb

module PublishableSpec

describe “Publishable”, :shared => true do
it “should have a published marker” do
@model.save!
@model.should_not be_published
end

it "should be publishable" do
 @model.save.publish!
 @model.should be_published
end

end
end

I can post more if that’s unclear (showing the actual AR classes and
mixin), but it seems to work well and eliminates duplication. I hope
the formatting on this comes through…

Jim L.
http://jimlindley.com

Yeah, this is fine for a simple mixin with only one shared behaviour,
but the problem is that a real chunk of mixed-in functionality will
probably need many behaviours that correspond to different initial
states (provided you’re behaving yourself and not doing too much state
setup within the individual examples).

Tom, there is likely a better path then the one I’m going down, and I
would love to hear it. I am no RSpec expert. How big are the modules
you’re including?

For the modules I do this with it doesn’t seem to get out of hand. The
example I gave above was a simplifed version of a module spec, not the
whole thing. The real one has many more behaviour blocks, and in the
before block a couple hashes for use inside the module spec for
creating other scenarios. I’m not doing much setup inside the module
spec. If the module has a couple aspects to its behaviour I usually
end up with just 2 or 3 describe blocks each with about 20 it blocks,
and testing its inclusion into AR classes just needs a before block
setting up a half dozen objects.

If it’s getting too complicated to spec out maybe the module is doing
too much and should be split up?

Jim

On Nov 6, 2007 8:11 AM, Tom S. [email protected] wrote:

before(:each) do
So, firstly, perhaps I’ll have ten shared behaviours to specify my
doing some kind of parameterized helper gymnastics where you pass in
the child class object and the shared behaviour calls #new on it?

None of this is impossible to do, it’s just that it all feels very
repetitious and difficult in contrast to the elegant solutions that
people often post here.

There really isn’t a great solution for this problem right now, but
there are a few initiatives that will be helpful in getting us there.
Nested specs, classes/methods (as an alternative to describe/it),
turning examples into methods (so they can get overridden), etc, etc.

I’m hoping that this sort of “okay, you
understand the basics, but NOW what?” issue is the kind of thing that
the hotly-anticipated RSpec book will address, because any information
about best practice in this area is really lacking, but I fear it
might not be that kind of book!

Well - there will be some of that, and we’ll certainly consider
including something about this issue. It’s fairly common.

Cheers,
David

On 6 Nov 2007, at 14:39, David C. wrote:

I’m hoping that this sort of “okay, you
understand the basics, but NOW what?” issue is the kind of thing that
the hotly-anticipated RSpec book will address, because any
information
about best practice in this area is really lacking
Well - there will be some of that, and we’ll certainly consider
including something about this issue. It’s fairly common.

Great! My personal experience has been that the nuts and bolts of
RSpec are pretty easy to pick up from the really rather good online
documentation – it’s the details of how to actually apply this stuff
to real projects that gets people confused about what “the right way”
is. (Witness the many discussions about how to spec ActiveRecord
validations, etc.)

Obviously a lot of this stuff is a matter of opinion and design
preference rather than cold mathematical fact, but someone putting a
stake in the ground and proclaiming a few best practices (at the right
level of abstraction, i.e. general enough to be applicable but
concrete enough to be useful) would be incredibly welcome. Can’t wait!

Cheers,
-Tom

On 6 Nov 2007, at 14:40, Jim L. wrote:

Tom, there is likely a better path then the one I’m going down, and I
would love to hear it. I am no RSpec expert.

Neither am I! From David’s response it sounds as though there isn’t a
particularly tidy way to solve this problem at the moment, so I guess
we just need to muddle along in whatever way works.

How big are the modules you’re including?
For the modules I do this with it doesn’t seem to get out of hand.
If it’s getting too complicated to spec out maybe the module is doing
too much and should be split up?

Possibly, but the proliferation of behaviours is mostly due to
following Dave A.’ “one expectation per example” guideline
(http://daveastels.com/2006/08/26/one-expectation-per-example-a-remake-of-one-assertion-per-test/
), which actually works out really well for regular specs, making them
easier to write and understand. It’s just the impedance mismatch
between this particular practice (i.e. split up big behaviours into
lots of smaller ones) and RSpec’s limited support for sharing
behaviours (i.e. you can’t group them together or supply parameters
when referencing them) that causes the hassle, rather than
(necessarily) a large or complicated mixin module.

Cheers,
-Tom