You are viewing an archived version of danielfischer.com

 

New RSpec Pattern to DRY up Your Controller Specs

Published: November 6th, 2007

There was a feature request on the RSpec mailing list, or the RSpec tracker on drying up the controller specs. Here’s a solution that David Chelmisky came up with; there’s even a snippet of helper code so you can incorporate this right away into your specs!

One of RSpec’s developers, David Chelimsky, released a little helper to
remedy a clunky pattern1 in the controller
specs2. David gave the following example as what is considered “clunky”, I’m sure you all do it, I know I do.

  describe PersonController, "handling failed POST to create" do
    def do_post
      post :create, invalid_arguments
    end
 
    it "should redisplay the create form" do
      do_post
      response.should render_template("people/new")
    end
 
    it "should try to create a Person" do
      Person.should_receive(:create).with(invalid_arguments).and_return(false)
      do_post
    end
  end

So, as a solution to the clunkiness in the example above, David proposed this:

  describe PersonController, "handling failed POST to create" do
    def do_post
      post :create, invalid_arguments
    end
 
    it "should redisplay the create form" do
      after_post do
        response.should render_template("people/new")
      end
    end
 
    it "should try to create a Person" do
      during_post do
        Person.should_receive(:create).with(invalid_arguments).and_return(false)
      end
    end
  end

I honestly have to say, that I like this style a lot. This style adds a lot more verbosity, and clarity to the point of controller speccing. I know that if I
were a beginner all over again, this would have removed a lot of confusion that I went through during those days.

The Helper

If you’d like to use this, you can simply copy and paste the following code and put it into spec_helper.rb:

  [:get, :post, :put, :delete, :render].each do |action|
    eval %Q{
      def before_#{action}
        yield
        do_#{action}
      end
      alias during_#{action} before_#{action}
      def after_#{action}
        do_#{action}
        yield
      end
    }
  end

Thanks to David Chelimsky for writing this out. I think this has potential to go into RSpec’s ruby_on_rails core, so far it’s just a helper.

How do you feel about this new pattern? Could you see this going into the RSpec ruby_on_rails core?

  1. There was a suggestion in the rspec tracker, or the mailing list about a feature to dry up the controller specs. []
  2. Specs are basically tests, but under a different mentality. RSpec adopts the philosophy of Behavior Driven Development, which imposes this new mentality
    of covering your code. []

+1 for this going in rspec core !
It’s super annoying to put the flash or render in the wrong place in a test, and get some non-helpful message. This puts a little flavor in so you’re more likely to behave yourself :)

gravatar
  • dylan
  • Dec 14th
Enter your comment

Ready. Set. Go.

In terms of the formatting, you're allowed to use markdown, textile, or basic html; it's truly up to you -- what strikes your fancy?

You don't have to worry about your e-mail address being sold to a russian-spam-mafia. I'm only going to use it for my own weird needs; like asking you out for a date on a lonely night of coding.