Is "it_should_behave_like" a code smell?

Consider the following simple Rails app:

==== begin snippet ====

lib/herpable.rb

module Herpable; …; end

app/models/…

class ClassOne; include Herpable; end
class ClassTwo; include Herpable; end

==== end snippet ====

What’s the better way to write specs for these? Would you put the
module into its own shared_example?

==== begin snippet ====

spec/models/class_one_spec.rb

describe ClassOne do
it_should_behave_like “Herpable”

end
==== end snippet ====

Or would you just test the module directly?

==== begin snippet ====

spec/lib/herpable_spec.rb

describe Herpable do
let(:herped) { Class.new { include Herpable } }

it “should be derp” do
herped.should_be derp
end
==== end snippet ====

I started thinking about this because I noticed there seemed to be a
lot of specs running in our shared examples. That gave rise to a
couple of internal questions:

1.) If you have a bunch of closely related code that always gets
tested together, why isn’t it already a class or module?
2.) If it is, then why don’t you just spec that instead?
3.) If you do, then what’s the best way to use shared_examples_for /
it_should_behave_like?

~ jf

John F.
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

On Jun 7, 2011, at 10:31 AM, John F. wrote:

==== end snippet ====
==== end snippet ====
end
it_should_behave_like?
There’s a section on this in The RSpec Book. Briefly:

  1. Host objects can override behavior (intentionally or otherwise), so
    spec’ing the module outside a host is insufficient. For these cases, I
    recommend using shared examples.

  2. Some modules do stuff (like validate stuff in the host) when they are
    included. For these cases I recommend spec’ing the module directly.

See
http://relishapp.com/rspec/rspec-core/dir/example-groups/shared-examples
for different approaches. I like “it_behaves_like”, or context-specific
aliases.

HTH,
David