<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Robby on Rails: RSpec: It Should Behave Like</title>
    <link>http://www.robbyonrails.com/articles/2008/08/19/rspec-it-should-behave-like</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts.sort_by{|t| t[:topic]}.collect </description>
    <item>
      <title>RSpec: It Should Behave Like</title>
      <description>&lt;p&gt;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&amp;#8217;t get the benefits of shared groups. Now that we have some time to go through and update some of our older specs, I&amp;#8217;ve been trying to take advantage of the features currently available in &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt;. One feature that I haven&amp;#8217;t seen a lot of mention of by people is shared groups, so I thought I&amp;#8217;d take a few minutes to write up a quick intro to using it.&lt;/p&gt;


	&lt;p&gt;To pick some low-hanging fruit, let&amp;#8217;s take an all-too-familiar method, which you might be familiar with&amp;#8230; &lt;code&gt;login_required&lt;/code&gt;. Sound familiar? Have you found yourself &lt;em&gt;stubbing&lt;/em&gt; &lt;code&gt;login_required&lt;/code&gt; over and over throughout your specs?&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;Admin&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;DohickiesController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;

  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stub!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:login_required&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;Dohicky&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:paginate&lt;/span&gt; &lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

 &lt;span class="punct"&gt;...&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;If you&amp;#8217;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 &lt;code&gt;describe&lt;/code&gt; block and load it into any other spec groups that you need. For example, in our case, we&amp;#8217;ll need to stub &lt;code&gt;login_required&lt;/code&gt; in several places. We can set this up in one shared group and reference it wherever necessary.&lt;/p&gt;


	&lt;p&gt;For example, here is what we&amp;#8217;ll start off with.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;an admin user is signed in&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stub!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:login_required&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;Admin&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;DohickiesController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="punct"&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;However, the new describe block isn&amp;#8217;t accessible from the block at the bottom of the example&amp;#8230; yet. To do this, we just need to pass the option: &lt;code&gt;:shared =&amp;gt; true&lt;/code&gt; as you&amp;#8217;ll see in the following example.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;an admin user is signed in&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:shared&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stub!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:login_required&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Great, now we can reference it by referring to it with: &lt;code&gt;it_should_behave_like SharedGroupName&lt;/code&gt;. In our example above, this would look like:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;an admin user is signed in&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stub!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:login_required&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;Admin&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;DohickiesController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;it_should_behave_like&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;an admin user is signed in&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="constant"&gt;Dohicky&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:paginate&lt;/span&gt; &lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:index&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

 &lt;span class="punct"&gt;...&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;Admin&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;DohickiesController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;it_should_behave_like&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;an admin user is signed in&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:each&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="attribute"&gt;@dohicky&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mock_model&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="constant"&gt;Dohicky&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;Dohicky&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="symbol"&gt;:new&lt;/span&gt; &lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="attribute"&gt;@dohicky&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:new&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="punct"&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;That&amp;#8217;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&amp;#8217;ll have a single place to change in our specs. (&lt;strong&gt;tip:&lt;/strong&gt; you can put these in your &lt;code&gt;spec_helper&lt;/code&gt; file)&lt;/p&gt;


	&lt;p&gt;You can learn more about &lt;code&gt;it_should_behave_like&lt;/code&gt; and other helpful features on the &lt;a href="http://rspec.info/documentation/"&gt;RSpec documentation site&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;If you have any suggestions on better ways of handling things like this, please follow up and share your solutions. I&amp;#8217;m always looking to sharpen my tools. :-)&lt;/p&gt;


	&lt;h3&gt;Update&lt;/h3&gt;


	&lt;p&gt;In response, &lt;a href="http://brynary.com/"&gt;Bryan Helmkamp&lt;/a&gt; suggests that a better solution is to define a method in our specs like, for example: &lt;code&gt;build_mock_user_and_login&lt;/code&gt;. then calling it in our &lt;code&gt;before(:each)&lt;/code&gt;. So, maybe the approach above isn&amp;#8217;t the most ideal method but I did wantt o draw some attention to &lt;code&gt;it_should_behave_like&lt;/code&gt;. I suppose that I need a better example.. another post, perhaps? :-)&lt;/p&gt;


	&lt;p&gt;Also, Ed Spencer has posted an article titled, &lt;a href="http://edspencer.net/2008/08/drying-up-your-crud-controller-rspecs.html"&gt;DRYing up your &lt;span class="caps"&gt;CRUD&lt;/span&gt; controller RSpecs&lt;/a&gt;, which will introduce you mor to &lt;code&gt;it_should_behave_like&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Thanks for feedback people!&lt;/p&gt;


	&lt;h3&gt;Related Posts&lt;/h3&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.robbyonrails.com/articles/2007/02/13/be-careful-that-you-dont-stub-your-big-toe"&gt;Be Careful that you don&amp;#8217;t Stub your Big Toe&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.robbyonrails.com/articles/2007/08/02/spec-your-views"&gt;Spec Your Views&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
</description>
      <pubDate>Tue, 19 Aug 2008 21:47:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:769c7a25-afa3-40aa-aeb4-98c2ac61115a</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2008/08/19/rspec-it-should-behave-like</link>
      <category>Ruby on Rails</category>
      <category>Ruby</category>
      <category>Programming</category>
      <category>development</category>
      <category>rspec</category>
      <category>controllers</category>
      <category>rubyonrails</category>
      <category>rails</category>
      <category>agile</category>
      <category>tutorial</category>
      <category>specs</category>
      <category>code</category>
    </item>
  </channel>
</rss>
