I was going through an older project of ours and cleaning up some specs
and noticed how often we were doing the same thing in several places.
When we started the project, we didnāt get the benefits of shared
groups. Now that we have some time to go through and update some of our
older specs, Iāve been trying to take advantage of the features
currently available in RSpec. One feature that I
havenāt seen a lot of mention of by people is shared groups, so I
thought Iād take a few minutes to write up a quick intro to using it.
To pick some low-hanging fruit, letās take an all-too-familiar method,
which you might be familiar with⦠login_required
. Sound familiar?
Have you found yourself stubbing login_required
over and over
throughout your specs?
describe Admin::DohickiesController, āindexā do
before( :each ) do
controller.stub!( :login_required )
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
ā¦
end\
If youāre requiring that a user should be logged in when interacting
with most of the application (as in the case of an administration
section/namespace), you might want to consolidate some of your work into
one shared specification group. The basic premise behind this is that
you can write a typical describe
block and load it into any other spec
groups that you need. For example, in our case, weāll need to stub
login_required
in several places. We can set this up in one shared
group and reference it wherever necessary.
For example, here is what weāll start off with.
describe āan admin user is signed inā do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, āindexā do
ā¦\
However, the new describe block isnāt accessible from the block at the
bottom of the example⦠yet. To do this, we just need to pass the
option: :shared => true
as youāll see in the following example.
describe āan admin user is signed inā, :shared => true do
ruby\
`before( :each ) do
ruby\
controller.stub!( :login_required )ruby\
`end
ruby
end
``ruby\
Great, now we can reference it by referring to it with:
it_should_behave_like SharedGroupName
. In our example above, this
would look like:
describe āan admin user is signed inā do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, āindexā do
it_should_behave_like āan admin user is signed inā
before( :each ) do
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
ā¦
end
describe Admin::DohickiesController, ānewā do
it_should_behave_like āan admin user is signed inā
before( :each ) do
dohicky = mock_model( Dohicky ) Dohicky.should_receive( :new ).and_return(
dohicky
)
get :new
end
ā¦\
Thatās it! Pretty simple, eh? We can now reference this shared group in
any describe blocks that we want to. A benefit to this approach is that
we can make change the authentication system (say, we decide to switch
it entirely and/or even just change method names, set any other
prerequisites necessary when an admin is signed in), weāll have a single
place to change in our specs. (tip: you can put these in your
spec_helper
file)
You can learn more about it_should_behave_like
and other helpful
features on the RSpec documentation
site.
If you have any suggestions on better ways of handling things like this,
please follow up and share your solutions. Iām always looking to sharpen
my tools. :-)
Update
In response, Bryan Helmkamp suggests that a
better solution is to define a method in our specs like, for example:
build_mock_user_and_login
. then calling it in our before(:each)
. So,
maybe the approach above isnāt the most ideal method but I did wantt o
draw some attention to it_should_behave_like
. I suppose that I need a
better example.. another post, perhaps? :-)
Also, Ed Spencer has posted an article titled, DRYing up your CRUD
controller
RSpecs,
which will introduce you mor to it_should_behave_like
.
Thanks for feedback people!
Related Posts
- [Be Careful that you donāt Stub your Big
Toe](http://www.robbyonrails.com/articles/2007/02/13/be-careful-that-you-dont-stub-your-big-toe)
```text
- [Spec Your
```text
Views](http://www.robbyonrails.com/articles/2007/08/02/spec-your-views)