Mark Gandolfo's Blog
How To: Rspec And Factory Girl
I thought i'd add a quick how to, on setting up Factory Girl and RSpec
First lets install some gems
The below command will install rspec and factory girl as well as a bunch of dependencies if you don't have them already.
sudo gem install rspec rspec-rails thoughtbot-factory_girl
And configure your app
Now in your rails app, add the following to your environment/test.rb file (you can leave the version symbol out to always fetch the latest).
# /config/environment/test.rb
config.gem "rspec", :lib => false, :version => ">=1.2.6"
config.gem "rspec-rails", :lib => 'spec/rails', :version => ">=1.2.6"
config.gem "thoughtbot-factory_girl", :lib => "factory_girl", :version => ">=1.2.2", :source => "http://gems.github.com"
Lets generate the rspec skeleton and configure factories
Now that we have our gems set up ready to roll, in your rails app run the below command, This will generate a /spec directory and create a spec_helper.rb file.
script/generate rspec
Now in the spec directory create a factories folder. This will be the place you can store the definitions for each factory.
mkdir spec/factories
In your spec_helper.rb file, add the following require's to ensure everything is loaded when your tests run.
# spec/spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))
require 'spec/autorun'
require 'spec/rails'
require 'factory_girl'
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
Spec::Runner.configure do |config|
config.use_transactional_fixtures = true
config.use_instantiated_fixtures = false
end
Factory girl should magically find all of your factories in that folder, but in one of my applications it didn't. I'm not sure why, and i didn't have the time to check, so i manually included them. To do this, in your spec_helper.rb file, add the following line, right above the "Spec::Runner".
Dir[File.expand_path(File.join(File.dirname(__FILE__),'factories','**','*.rb'))].each {|f| require f}
An example of how it all comes together
And you should be good to roll.. I'll give you a quick example of a factory and a simple spec, just to get you running. So if I had a Company model, I could test that model as such
# spec/factories/companies.rb
Factory.sequence :name do |n|
"company name #{n}"
end
Factory.define :company do |c|
c.name { Factory.next(:name) }
c.add_attribute :description, 'company description'
c.add_attribute :subdomain, 'company_name '
end
So I'm defining the factory called :company, and it has three fields. A name, description and subdomain. You'll notice I've defined name a little differently than description and subdomain. Thats because I want my name to incremental (i.e. I don't want two company names to be the same). Now each time i create a company factory, the name will increment by 1.
For a full break down on all of the magick of factories, check out the Factory Girl Github page.
Next, lets do some rspec magick.
So in my spec/models/ directory create a new file called company_spec.rb and here is a basic company test, using Factories
require 'spec_helper'
describe Company do
before(:each) do
@company = Factory(:company)
end
it "should create a new instance given valid attributes" do
@company.should be_instance_of(Company)
end
end
You can see by doing Factory(:company) I'm building a new factory and storing it in @company. Its as simple as that, no more messy fixtures.
Here are some resources to help you with rspec
Another Cheat Sheet (PDF WARNING)
And Another Cheat Sheet (PDF WARNING)
Good luck with testing!