Unpopular Developer 5: Stop Unit Testing Your Scaffold Controllers

Mike Burns

This goes out to all the veteran Ruby on Rails developers: those who have the RESTful scaffold memorized down to their fingertips; those who can write the tests for it using Cucumber with Webrat, Rails integration tests with Webrat, Rails controller tests with RSpec, Test::Unit, or Shoulda, using mocking, stubbing, test spies, or old-school assertion style:

Stop unit testing the RESTful scaffold

Do write an integration test with Webrat (and Cucumber or Rails integration tests or some crazy script using Hubris), but abstract that out as much as you can. It’s the scaffold. You know it works.

You should write a unit test for your RESTful controller as soon as it deviates, and you should test-drive that deviation both in the integration test and the unit test.

Here, some code. First the #index action, non-tested:

def index
  @posts = Post.all
end

It works. No unit test will uncover a bug in this. The integration test may - for example, Post may have no database table yet, or it may not derive from ActiveRecord::Base, or may redefine Post.all, or anything else - but the unit test for the controller will fail due to a regression.

So now we’ll make a change: posts should be listed alphabetically.

Feature: Posts
  # ... existing scenarios that test everything go here ...
  Scenario: Viewing posts alphabetically
    Given a post exists with a title of "Abe rents storage space"
    And a post exists with a title of "Aaron opens his garage to friends"
    When I go to the list of posts
    Then I should see the posts sorted alphabetically

Make sure that fails. Then add the unit test for the controller; the very first unit test for this controller. Here I’ll use shoulda and jferris-mocha:

require 'test_helper'

class PostsControllerTest < ActionController::TestCase
  should "alphabeticalize the blog posts on GET to index" do
    Post.stubs(:alphabetical).returns([])
    get :index
    assert_received(Post, :alphabetical) {|expects| expects.with()}
  end
end

That’s all you need because that’s all that has deviated from the RESTful scaffold.

Benefits

  • See what deviates from the RESTful scaffold.
  • Refactor with ease.
  • Spend less time implementing controller unit tests.

The Opposite of Benefits

  • Requires your team to know the RESTful scaffold well.

So in summary, do write integration tests all the time, but don’t TATFT. Relax those unit tests.