Skip to content

Ed Gibbs - Musings of a Software Development Manager
Syndicate content
Lessons from managing developers
Updated: 4 hours 14 min ago

Stubbing Partials with RSpec in Rails View Tests

Sun, 11/20/2011 - 00:59

Working with my pair yesterday we ran into an issue testing a view that pulled in several partials. In the interest of making progress we punted after about half an hour of trying to setup expectations on the partials and just tested the negative cases where we didn’t have to worry about the partials being called. Intellectual curiosity and not wanting to leave the views lightly tested I dived into seeing how we could effectively test that the partials were called as expected.

Say you have a view like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="content">
  <div id="page_title" style="padding-bottom: 20px">
    <h2>Books</h2>
  </div>
  < %= render :partial => 'tabs' %>

  < % if @books.empty? -%>
      <em>No Books</em><em>
  < % else %>
      < %= pagination_links = render :partial => 'shared/pagination', :object => @books %>
      < %= render :partial => "book_rows", :locals => {:books => @books} %>
      < %= pagination_links %>
  < % end %>
</em></div>

You want to test the conditional to see that the partials to display the list of books work correctly. You don’t want to worry about concerns like setting up the books collection, and you might even want to stub out the call to the partial that displays the tabs a the top of the page.

The Rspec example group for this looks like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
require 'spec_helper'

describe "books.rhtml" do
  before(:each) do
    assigns[:books] = []
  end

  describe "with no books" do
    it "should display 'No Books' message" do
      render
      response.should have_text(/No Books/)
    end
  end

  describe "with books" do
    before(:each) do
      assigns[:books] = [Factory.build(:book)]
      template.stub(:render).with(hash_including(:partial => "tabs"))
      template.stub(:render).with(hash_including(:partial => "shared/pagination"))
    end

    it "should render book rows" do
      template.should_receive(:render).with(hash_including(:partial => "book_rows"))
      render
    end
  end
end

The key find was to use with(:hash_including()) which I found from a helpful link at Stack Overflow.

Categories: Blogs

Breaking the Build at the New Job

Sun, 09/18/2011 - 05:43
I broke the build

My first break of the CI build on a new team came about two weeks into starting the new job. We had made a small change to a dynamically created URL on a single page of the application. Normally this would fall into the category of “too simple to test” for me. My pairing partner pointed out when we started the story that we should put a test in for the change. I argued that changing a URL was too simple a change to bother writing a test for. He disagreed, but let me go ahead after some further discussion. After checking in the feature, about an hour later a developer on the other side of the room piped up with “Someone broke the build.” My pairing partner smiled and said, “I guess we didn’t need to test that.”

It turned out there was another test I didn’t realize had a dependency on that same link and by changing it we had broken an assertion on the specific URL. A bit embarrassed I learned an important lesson. My assumptions about “too simple to break” needed some adjusting.

Over the course of several weeks I came to appreciate that many things were worth testing. A particularly revealing example was testing a new javascript dialog. Javascript is always a pain point when it comes to unit testing, and I’ve often let that coverage of javascript functionality be covered by functional tests usually with Selenium. My pairing partner walked me through a complete TDD approach asserting every part of the function we created and the various DOM elements we used to create it. I did ask a few questions about whether we really needed to test that we had created a DOM element in some exact order at points, but he was firm about testing in every piece. By the end of the feature I had a new appreciation for doing very low level unit testing.

I love that I’m being challenged on not writing enough tests. For so long in past shops I was the hardcore TDD advocate constantly questioned about the real need for testing some component. Now I’m learning to test in even very small changes.

Categories: Blogs