[rspec-users] Is "it_should_behave_like" a code smell?

David Chelimsky dchelimsky at gmail.com
Tue Jun 7 12:04:15 EDT 2011


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

> 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?

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


More information about the rspec-users mailing list