Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
doing it again and again

Here’s an RSpec trick I discovered yesterday. Sometimes when you’re writing a test you want to loop over some precondition data. But if you do a loop inside your test (or spec), then all the cases will be subsumed in a single test method (or “it” block). This means you’ll have the following problems:

  • The first case to fail will cause the rest of the cases not to run. It’d be nice to see them all in a single test run.
  • You won’t take advantage of RSpec’s cool self-documenting trick of labeling each it block with a full description of the failure, and it’ll be harder to debug which case failed.
  • If you’re calling into Rails (e.g. in a View spec), you’ll only be able to call certain methods — especially render — once per test method. That means that you simply can’t use a loop inside a method to collapse redundant tests into a single block.

Ruby to the rescue! Instead of looping inside your it block, loop outside your it block.

require 'hpricot'

describe "navbar" do

  TABS = ["Home", "Articles", "Comments", "Preferences"]
  TABS.each do |tab|
    it "selects tab #{tab}" do
      assigns[:current_navbar_tab] = tab
      render "/shared/_navbar.mab"
      doc = Hpricot(response.body)
      doc.at("//li[@class=active]/a").inner_html.should == tab
    end
  end

end

When I mentioned this at standup, Nathan mentioned the eval module… maybe he or someone else can add more detail in a comment?

Note that this technique should be used sparingly. It’s kind of a test smell to have loops, but it’s useful in certain cases… In this example it’s actually different code rendering each separate tab. If we spent a bit more time and extracted a Tab object then we could possibly get away with just unit testing that class and trusting it to render properly on the page for each actual tab.

Comments
Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *