Home · Blog · Talks · Projects

Fed up with Rails fixtures? (part one)

In a previous post I explained why I’m not a big fan of Rails fixtures. But how can you avoid using them and still obtain good test coverage? Try forgetting about fixtures and writing unit tests that only test a single class and nothing else. Here’s an example where you hardly1 need to involve the database at all…

class Initial < ActiveRecord::Migration
  def self.up
    create_table :companies do |t|
      t.column :name, :string
    end
    create_table :employees do |t|
      t.column :company_id, :integer
      t.column :salary, :integer
    end
  end
end
class Company < ActiveRecord::Base
  has_many :employees
  def wage_bill
    employees.inject(0) { |total, employee| total + employee.salary }
  end
end
class Employee < ActiveRecord::Base
  belongs_to :company
end

So instead of writing this…

# companies.yml
walmart:
  id: 1
  name: Walmart

# employees.yml
fred:
  id: 1
  company_id: 1
  salary: 10000
anne:
  id: 2
  company_id: 1
  salary: 20000
class CompanyTest < Test::Unit::TestCase
  fixtures :companies, :employees
  def test_should_calculate_wage_bill
    assert_equal 30000, companies(:walmart).wage_bill
  end
end

You can write this…

class CompanyTest < Test::Unit::TestCase
  def test_should_calculate_wage_bill
    employees = []
    employees << Employee.new(:salary => 10000)
    employees << Employee.new(:salary => 20000)
    company = Company.new(:employees => employees)
    assert_equal 10000 + 20000, company.wage_bill
  end
end

This way you home in on the behaviour of the Company#wage_bill method and avoid testing the ActiveRecord code and access to the database. More ways to avoid hitting the database will follow in another post.

1 ActiveRecord still needs to know what columns in each table e.g.

SHOW FIELDS FROM companies
Contact · History · Colophon · Links