<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ #rspec - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ #rspec - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 11 Jun 2026 23:15:40 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/rspec/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to DRY out your RSpec Tests using Shared Examples ]]>
                </title>
                <description>
                    <![CDATA[ By Parth Modi “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.” — Abraham Lincoln When I refactored a project a few weeks ago, I spent most of my time writing specs. After writing several similar test cases... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-dry-out-your-rspec-tests-using-shared-examples-d5cc5d33fd76/</link>
                <guid isPermaLink="false">66c351cb765a634c3485fe0c</guid>
                
                    <category>
                        <![CDATA[ #rspec ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby on Rails ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TDD (Test-driven development) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 04 Feb 2017 00:00:00 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*5Cb4TjFan4h4eM3JsCqrbA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Parth Modi</p>
<blockquote>
<p>“<em>Give me six hours to chop down a tree and I will spend the first four sharpening the axe.” — Abraham Lincoln</em></p>
</blockquote>
<p>When I refactored a project a few weeks ago, I spent most of my time writing specs. After writing several similar test cases for some APIs, I started to wonder whether I might be able to get rid of a lot of this duplication.</p>
<p>So I threw myself into reading up on the best practices for DRYing up tests (Don’t Repeat Yourself). And that’s how I came to know of <code>shared examples</code> and <code>shared contexts</code>.</p>
<p>In my case, I ended up using shared examples. And here’s what I’ve learned so far from applying these.</p>
<p>When you have multiple specs that describe similar behavior, it might be better to extract redundant examples into <code>shared examples</code> and use them in multiple specs.</p>
<p>Suppose you have two models <em>User</em> and <em>Post</em>, and a user can have many posts. Users should be able to view list of users and posts. Creating an index action in the users and posts controllers will serve this purpose.</p>
<p>First, write specs for your index action for the users controller. It will have the responsibility of fetching users and rendering them with proper layout. Then write enough code to make tests pass.</p>
<pre><code># users_controller_spec.rbdescribe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>  before <span class="hljs-keyword">do</span>     <span class="hljs-number">5.</span>times <span class="hljs-keyword">do</span>      FactoryGirl.create(:user)     end    get :index  end  it {  expect(subject).to respond_with(:ok) }  it {  expect(subject).to render_template(:index) }  it {  expect(assigns(:users)).to match(User.all) }end
</code></pre><pre><code># users_controller.rbclass UsersController &lt; ApplicationController  ....  def index    @users = User.all  end  ....end
</code></pre><p>Typically, the index action of any controller fetches and aggregates data from few resources as required. It also adds pagination, searching, sorting, filtering and scoping.</p>
<p>Finally, all these data are presented to views via HTML, JSON, or XML using APIs. To simplify my example, the index actions of controllers will just fetch data, then show them via views.</p>
<p>The same goes for the index action in the posts controller:</p>
<pre><code>describe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>   before <span class="hljs-keyword">do</span>     <span class="hljs-number">5.</span>times <span class="hljs-keyword">do</span>      FactoryGirl.create(:post)    end    get :index  end  it {  expect(subject).to respond_with(:ok) }  it {  expect(subject).to render_template(:index) }  it {  expect(assigns(:posts)).to match(Post.all) }end
</code></pre><pre><code># posts_controller.rbclass PostsController &lt; ApplicationController  ....  def index    @posts = Post.all  end  ....end
</code></pre><p>RSpec tests written for both users and posts controller are very similar. In both controllers we have:</p>
<ul>
<li>The response code — should be ‘OK’</li>
<li>Both index action should render proper partial or view — in our case <code>index</code></li>
<li>The data we want to render, such as posts or users</li>
</ul>
<p>Let’s DRY the specs for our index action by using <code>shared examples</code>.</p>
<h3 id="heading-where-to-put-your-shared-examples">Where to put your shared examples</h3>
<p>I like to place shared examples inside the _specs/support/shared<em>examples</em> directory so that all <code>shared example</code>-related files are loaded automatically.</p>
<p>You can read about other commonly used conventions for locating your <code>shared examples</code> here: <a target="_blank" href="https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples">shared examples documentation</a></p>
<h3 id="heading-how-to-define-a-shared-example">How to define a shared example</h3>
<p>Your index action should respond with 200 success code (OK) and render your index template.</p>
<pre><code>RSpec.shared_examples <span class="hljs-string">"index examples"</span> <span class="hljs-keyword">do</span>   it { expect(subject).to respond_with(:ok) }  it { expect(subject).to render_template(:index) }end
</code></pre><p>Apart from your <code>it</code> blocks — and before and after your hooks — you can add <code>let</code> blocks, context, and describe blocks, which can also be defined inside <code>shared examples</code>.</p>
<p>I personally prefer to keep shared examples simple and concise, and don’t add contexts and let blocks. The <code>shared examples</code> block also accepts parameters, which I’ll cover below.</p>
<h3 id="heading-how-to-use-shared-examples">How to use shared examples</h3>
<p>Adding <code>include_examples "index examples"</code> to your users and posts controller specs includes “index examples” to your tests.</p>
<pre><code># users_controller_spec.rbdescribe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>  before <span class="hljs-keyword">do</span>     <span class="hljs-number">5.</span>times <span class="hljs-keyword">do</span>      FactoryGirl.create(:user)     end    get :index  end  include_examples <span class="hljs-string">"index examples"</span>  it {  expect(assigns(:users)).to match(User.all) }end
</code></pre><pre><code># similarly, <span class="hljs-keyword">in</span> posts_controller_spec.rbdescribe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>  before <span class="hljs-keyword">do</span>     <span class="hljs-number">5.</span>times <span class="hljs-keyword">do</span>      FactoryGirl.create(:post)     end    get :index  end  include_examples <span class="hljs-string">"index examples"</span>  it {  expect(assigns(:posts)).to match(Post.all) }end
</code></pre><p>You can also use <code>it_behaves_like</code> or <code>it_should_behaves_like</code> instead of <code>include_examples</code> in this case. <code>it_behaves_like</code> and <code>it_should_behaves_like</code> are actually aliases, and work in same manner, so they can be used interchangeably. But <code>include_examples</code> and <code>it_behaves_like</code> are different.</p>
<p>As stated in the official documentation:</p>
<ul>
<li><code>include_examples</code> — includes examples in the current context</li>
<li><code>it_behaves_like</code> and <code>it_should_behave_like</code> include the examples in a nested context</li>
</ul>
<h4 id="heading-why-does-this-distinction-matter">Why does this distinction matter?</h4>
<p>RSpec’s documentation gives a proper answer:</p>
<blockquote>
<p><em>When you include parameterized examples in the current context multiple times, you may override previous method definitions and last declaration wins.</em></p>
</blockquote>
<p>So when you face situation where parameterized examples contain methods that conflict with other methods in same context, you can replace <code>include_examples</code> with <code>it_behaves_like</code> method. This will create a nested context and avoid this kind of situations.</p>
<p>Check out the following line in your users controller specs, and posts controller specs:</p>
<pre><code>it { expect(assigns(:users)).to match(User.all) }it { expect(assigns(:posts)).to match(Post.all) }
</code></pre><p>Now your controller specs can be re-factored further by passing parameters to shared example as below:</p>
<pre><code># specs/support/shared_examples/index_examples.rb
</code></pre><pre><code># here assigned_resource and resource <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">are</span> <span class="hljs-title">parameters</span> <span class="hljs-title">passed</span> <span class="hljs-title">to</span> <span class="hljs-title">index</span> <span class="hljs-title">examples</span> <span class="hljs-title">block</span> <span class="hljs-title">RSpec</span>.<span class="hljs-title">shared_examples</span> "<span class="hljs-title">index</span> <span class="hljs-title">examples</span>" <span class="hljs-title">do</span> |<span class="hljs-title">assigned_resource</span>, <span class="hljs-title">resource_class</span>|   <span class="hljs-title">it</span> </span>{ expect(subject).to respond_with(:ok) }  it { expect(subject).to render_template(:index) }  it {  expect(assigns(assigned_resource)).to match(resource_class.all)   }end
</code></pre><p>Now, make following changes to your users and posts controller specs:</p>
<pre><code># users_controller_spec.rbdescribe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>  before <span class="hljs-keyword">do</span>     ...  end  include_examples <span class="hljs-string">"index examples"</span>, :users, User.allend
</code></pre><pre><code># posts_controller_spec.rbdescribe <span class="hljs-string">"GET #index"</span> <span class="hljs-keyword">do</span>  before <span class="hljs-keyword">do</span>     ...  end  include_examples <span class="hljs-string">"index examples"</span>, :posts, Post.allend
</code></pre><p>Now controller specs look clean, less redundant and more importantly, DRY. Furthermore, these index examples can serve as basic structures for designing the index action of other controllers.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>By moving common examples into a separate file, you can eliminate duplication and improve the consistency of your controller actions throughout your application. This is very useful in case of designing APIs, as you can use the existing structure of RSpec tests to design tests and create APIs that adhere to your common response structure.</p>
<p>Mostly, when I work with APIs, I use <code>shared examples</code> to provide me with a common structure to design similar APIs.</p>
<p>Feel free to share how you DRY up your specs by using <code>shared examples</code>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
