Testing Views by Not Testing Views: Or, The Presenter Pattern

October 19, 2007 Pivotal Labs

Err The Blog asks: “What’s the best way to test views?”

I think the best way to test views is not to test views. Extract all logic from the view into a model or presenter where it can be unit tested. Your views are then mostly declarative and there’s minimal need to test them.

Here’s an example of the “presenter pattern”.

def create_or_destroy_friendship_link(friend)
  if current_user.friends_with?(friend)

You don’t need a special class to do a Presenter; a good old-fashioned layer of abstraction will do. The basic idea is to write all conditional+iterative view logic in such a way as to never call a Rails helper directly, or generate any HTML directly, or generate any strings directly. The logic merely delegates to other methods closer to the metal.

Tests then become fairly simple. Write tests of the higher-level conditional/iterative logic in terms of the lower-level methods:

describe FriendshipsHelper, '#create_or_destroy...' do
  it "renders create link when two users are not friends" do
    bob.should_not be_friends_with(users(:amy))
    create_or_destroy_friendship_link.should == create_friendship_link

This minimizes the need for view specs. I find in practice that a high percentage of view tests slow development down””they’re implemented not to aid development (since you typically debug views in-browser), but to prevent regression (i.e., they minimize the likelihood of introducing defects later). But since views are one of the most variable parts of a web application, regression tests are of the least value.

As a side note, I love integrate_views — not because I like to make assertions about the view in my controller tests, but because I hate mocks! I want a controller test to fail if I have a syntax error in my view!

About the Author


Making Rails Wicked Fast: Pagecaching Highly Personalized Web Pages
Making Rails Wicked Fast: Pagecaching Highly Personalized Web Pages

Consider the following snippet for a page showing blog articles. Notice how content on the page differs bas...


I've revised and extended my old talk on Test-Driven Development. Here it is as a nice PDF, and below the f...