My Beautiful Controller Spec

Posted by John Wulff Fri, 15 Feb 2008 23:21:00 GMT

Today I spent a few hours refining my controller rspec pattern. I’m really pleased with it.

This controller:
class AssignmentsController < ApplicationController  
  def index
    if params[:person_id]
      @person = Person.find params[:person_id]
      @assignments = @person.assignments
      @title = "Assignments for #{@person}"
    elsif params[:course_id]
      @course = Course.find params[:course_id]
      @assignments = @course.assignments
      @title = "Assignments for #{@course}"
    else
      @assignments = Assignment.find :all
      @title = "All Assignments"
    end

    @ical_url = url_for({ :format => :ics }.merge(params))
    @rss_url = url_for({ :format => :rss }.merge(params))
  end
end
Gets this spec:
require File.dirname(__FILE__) + '/../spec_helper'

describe AssignmentsController do
  describe 'index action GET request with' do
    describe 'no parameters' do
      before(:each)                    do get 'index' end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == 'All Assignments' end
      it 'should assign assignments'   do assigns[:assignments].should == Assignment.find(:all) end
    end

    describe 'a valid person_id' do
      before(:each)                    do get 'index', :person_id => (@person = test_person) end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == "Assignments for #{@person}" end
      it 'should assign assignments'   do assigns[:assignments].should == @person.assignments end
    end

    describe 'a valid course_id' do
      before(:each)                    do get 'index', :course_id => (@course = test_course) end
      it 'should successfully respond' do response.should be_success end
      it 'should assign a title'       do assigns[:title].should == "Assignments for #{@course}" end
      it 'should assign assignments'   do assigns[:assignments].should == @course.assignments end
    end

    describe 'any valid parameters' do
      before(:each)                    do get 'index' end
      it 'should assign a rss_url'     do assigns[:rss_url].should == 'http://test.host/assignments.rss' end
      it 'should assign an ical_url'   do assigns[:ical_url].should == 'http://test.host/assignments.ics' end
    end
  end
end

Liberal use of nesting, alignment, and inline assignments, hooray.

Beautiful specs mean I’m that much more likely to actually write them…

Can it get any better?

Validation Assertions

Posted by John Wulff Tue, 26 Jun 2007 19:06:00 GMT

I like to test my validations. While I don’t really care to test the underlying code that runs the validations (I trust the Rails team to make sure they work as advertised) I do like the reassurance that I didn’t screw up. So, I’ve written this small plugin to help me test my validations.

It works simply. In one of your models you’ve got a validation like this:
class User < ActiveRecord::Base
  validates_presence_of :name
  validates_length_of :name, :in => 4..26
  validates_uniqueness_of :name
end
To test the validations:
class UserTest < Test::Unit::TestCase  
  # Assert that a User's name must exist for validations to pass.
  def test_validates_presence_of_name
    assert_validates_presence_of User, :name
  end

  # Assert that a User's name must be at least 4 characters in length for
  # validations to pass.
  def test_validates_minimium_length_of_name
    assert_validates_minimum_length_of User, :name, 4
  end

  # Assert that a User's name must be less than 26 characters in length for
  # validations to pass.
  def test_validates_maximum_length_of_name
    assert_validates_maximum_length_of User, :name, 26
  end

  # Assert that a User's name must be unique for validations to pass.
  def test_validates_uniqueness_of_name
    assert_validates_uniqueness_of User, :name
  end
end

That’s it. Now you can rest easy know that your validations are really, really, really in place.

To install the plugin:
script/plugin install http://validation-assertions.googlecode.com/svn/trunk/validation_assertions/

Google Code Project Page