RSpec on Rails tip - Weaning myself off of fixtures

Posted by david

As I've used RSpec more, I've grown less and less fond of fixtures for Rails testing. In everything except model specs, I use mocks for the models and don't touch the database. Sometimes, however, I still want to test the database interaction in my model specs.

I'm working on a project that has plenty of existing test cases (both RSpec and Test::Unit) that depend on fixtures. As much as I'd like to eliminate that dependency, the show must go on, and I need to keep writing specs for new functionality. When I create a new model spec that does test database interaction, I want the database to be in a known state at the start of each spec - and the easiest known state to work with is empty, so today I whipped up the following snippet to empty out relevant tables at the beginning of each spec run:


# Wean ourselves off of fixtures
# Call this within the description (e.g., after the describe block) to remove everything from the associated class or table
module Spec
  module DSL
    module BehaviourCallbacks
      def reset_tables(*tables)
        callback = lambda do 
          tables.each do |table|
            ActiveRecord::Base.connection.delete("DELETE FROM #{table.to_s.tableize}")
          end
        end
        before_each_parts << callback
      end
    end
  end
end

If you drop this into your spec_helper.rb, then, in your specs, you can do the following:


require File.dirname(__FILE__) + '/../spec_helper'

describe BookOrders, "A newly created BookOrder" do

  reset_tables :book_orders, :books, :customer

  before(:each) do
    # setup some stuff
  end

  it "should require a customer" do
    # blah blah
  end

  # and so on
end