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) destroy_friendship_link(friend) else create_friendship_link(friend) end end
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 log_in(users(:bob)) bob.should_not be_friends_with(users(:amy)) create_or_destroy_friendship_link.should == create_friendship_link end end
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!