factory girl

Post on 05-Dec-2014

7.214 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

A not so brief overview of Factory Girl's features and basic usage.

TRANSCRIPT

Factory GirlA Brief Introduction Using Ruby on Rails

Factory GirlA Brief Introduction Using Ruby on Rails

Yet Another Blog Example

What’s Factory Girl?

A Replacement for Fixtures

Provides a Simple DSL

Keeps TestsFocused & Readable

Builds Objects Instead of Database Records

Installation

Gemfile

group :development, :test do gem ‘factory_girl_rails’end

Gemfile

$ bundle install

Defining a Factory

spec/factories/

spec/factories/users.rb

spec/factories/posts.rb

spec/factories/comments.rb

spec/factories/products.rb

spec/factories/users.rb

FactoryGirl.define do factory :user do name ‘Joe Blow’ email ‘joe.blow@example.com’ password ‘p@ssw0rd’ admin false endend

spec/factories/users.rb

spec/models/user_spec.rb

spec/models/user_spec.rb

describe User do

end

spec/models/user_spec.rb

describe User do subject { FactoryGirl.create(:user) }

end

spec/models/user_spec.rb

describe User do subject { FactoryGirl.create(:user) }

its(:name) { should == ‘Joe Blow’ }

end

spec/models/user_spec.rb

describe User do subject { FactoryGirl.create(:user) }

its(:name) { should == ‘Joe Blow’ } its(:email) { should == ‘joe.blow@example.com’ }

end

describe User do subject { FactoryGirl.create(:user) }

its(:name) { should == ‘Joe Blow’ } its(:email) { should == ‘joe.blow@example.com’ }

it { should_not be_admin }end

spec/models/user_spec.rb

FactoryGirl.create(:user)

FactoryGirl.build(:user)

FactoryGirl.build_stubbed(:user)

spec/spec_helper.rb

RSpec.configure do |config| config.include FactoryGirl::Syntax::Methodsend

spec/spec_helper.rb

FactoryGirl.create(:user)

create(:user)

build(:user)

build_stubbed(:user)

spec/models/user_spec.rb

describe User do subject { create(:user) }

its(:name) { should == ‘Joe Blow’ } its(:email) { should == ‘joe.blow@example.com’ }

it { should_not be_admin }end

Overriding Attributes

Keep Only Relevant Attributes in Tests

spec/models/user_spec.rb

context ‘a duplicate email address’ do it { should_not be_valid }end

context ‘a duplicate email address’ do let(:first_user) { User.create(name: ‘Joe First’, email: ‘joe@example.com’, password: ‘test123’, admin: false) } subject { User.new(name: ‘Joe Duplicate’, email: first_user.email, password: ‘test123’, admin: false) }

it { should_not be_valid }end

spec/models/user_spec.rb

context ‘a duplicate email address’ do let(:user) { create(:user) } subject { build(:user, email: user.email) }

it { should_not be_valid }end

spec/models/user_spec.rb

Lazy Attributes

Lazy Attributes Are Dynamic Attributes

spec/factories/posts.rb

FactoryGirl.define do factory :post do title ‘This is my post.’ content ‘There are many like it, but this one is mine.’ published_at Time.now endend

irb(main):001:0> FactoryGirl.create(:post)

irb(main):001:0> FactoryGirl.create(:post)=> #<Post id: 1, title: “This is my post.”, content: “There are many like it, but this one is mine.”, published_at: 2012-12-20 23:47:34 UTC>

group :development, :test do gem ‘factory_girl_rails’ gem ‘ffaker’end

Gemfile

spec/factories/posts.rb

FactoryGirl.define do factory :post do title { Faker::Lorem.sentence } content { Faker::Lorem.sentences.join(‘ ’) } published_at { Time.now } endend

irb(main):001:0> FactoryGirl.create(:post)

irb(main):001:0> FactoryGirl.create(:post)=> #<Post id: 2, title: “Lorem ipsum dolor sit amet, consectetur adipiscing elit.”, content: “Pellentesque adipiscing varius suscipit …”, published_at: 2012-12-20 23:48:14 UTC>

irb(main):001:0> FactoryGirl.create(:post)=> #<Post id: 3, title: “Nulla id augue ut mauris pharetra tincidunt ac sed velit.”, content: “Nullam tincidunt, dolor quis pellentesque …”, published_at: 2012-12-20 23:49:06 UTC>

Sequences

Reuse Common Attributes

FactoryGirl.define do sequence :email do |n| “person#{n}@example.com” endend

spec/factories/sequences.rb

FactoryGirl.define do factory :user do name { Faker::Name.name } email password ‘p@ssw0rd’ admin false endend

spec/factories/users.rb

Dependent Attributes

Attributes FromOther Attributes

spec/factories/users.rb

FactoryGirl.define do factory :user do name ‘Joe Blow’ email ‘joe.blow@example.com’ password ‘p@ssw0rd’ admin false endend

spec/factories/users.rb

FactoryGirl.define do factory :user do name ‘Joe Blow’ email { ‘#{name.gsub(/\s/, ‘.’)}@example.com’.downcase } password ‘p@ssw0rd’ admin false endend

irb(main):001:0> FactoryGirl.create(:user)=> #<User id: 1, name: “Joe Blow”, email: “joe.blow@example.com”, password: “p@ssw0rd”, admin: false>

irb(main):001:0> FactoryGirl.create(:user, name: ‘Joe Mama’)=> #<User id: 2, name: “Joe Mama”, email: “joe.mama@example.com”, password: “p@ssw0rd”, admin: false>

Traits

Specify Types Of Factories

describe Post do context ‘an unpublished post’ do subject { create(:post, published_at: nil) }

it ‘will never be read’ do # ... end endend

FactoryGirl.define do factory :post do title { Faker::Lorem.sentence } content { Faker::Lorem.sentences.join(‘ ’) } published_at { Time.now } endend

spec/factories/posts.rb

FactoryGirl.define do factory :post do title { Faker::Lorem.sentence } content { Faker::Lorem.sentences.join(‘ ’) } published_at { Time.now } trait :unpublished do published_at nil end endend

spec/factories/posts.rb

describe Post do context ‘an unpublished post’ do subject { create(:post, :unpublished) }

it ‘will never be read’ do # ... end endend

spec/models/post_spec.rb

Associations

Build Associated Objects From Factories

class Post < ActiveRecord::Base belongs_to :userend

app/models/post.rb

irb(main):001:0> FactoryGirl.create(:post)=> #<Post id: …, title: “…”, content: “…”, published_at: …, user: nil>

FactoryGirl.define do factory :post do title { Faker::Lorem.sentence } content { Faker::Lorem.sentences.join(‘ ’) } published_at { Time.now } trait :unpublished do published_at nil end endend

spec/factories/posts.rb

FactoryGirl.define do factory :post do user title { Faker::Lorem.sentence } content { Faker::Lorem.sentences.join(‘ ’) } published_at { Time.now } trait :unpublished do published_at nil end endend

spec/factories/posts.rb

irb(main):001:0> FactoryGirl.create(:post)=> #<Post …, user: #<User id: 123, name: “John Wayne”, …>>

Transient Attributes

Customize Behavior With Fake Attributes

FactoryGirl.define do factory :post do ignore do unapproved false end

title { unapproved ? “ಠ_ಠ” : “This is my post.” } endend

spec/factories/posts.rb

FactoryGirl.define do factory :post do ignore do unapproved false end

title { unapproved ? “ಠ_ಠ” : “This is my post.” } endend

spec/factories/posts.rb

FactoryGirl.define do factory :post do ignore do unapproved false end

title { unapproved ? “ಠ_ಠ” : “This is my post.” } endend

spec/factories/posts.rb

irb(main):001:0> FactoryGirl.create(:post)=> #<Post id: 2, title: “This is my post.”>

irb(main):001:0> FactoryGirl.create(:post, unapproved: true)=> #<Post id: 2, title: “ಠ_ಠ”>

Creating or Building Multiple Objects

Build a Shitload Of Objects

FactoryGirl.create_list(:model, 5)

FactoryGirl.build_list(:model, 5)

FactoryGirl.build_stubbed_list(:model, 5)

irb(main):001:0> FactoryGirl.create_list(:post, 5)

irb(main):001:0> FactoryGirl.create_list(:post, 5)=> [#<Post id: 1, title: “This is my post.”>, #<Post id: 2, title: “This is my post.”>, #<Post id: 3, title: “This is my post.”>, #<Post id: 4, title: “This is my post.”>, #<Post id: 5, title: “This is my post.”>]

Callbacks

Execute Arbitrary Code When Building & Creating

class User < ActiveRecord::Base has_many :postsend

app/models/user.rb

FactoryGirl.define do factory :user_with_posts do ignore do posts_count 5 end

after(:create) do |user, evaluator| FactoryGirl.create_list(:post, evaluator.posts_count, user: user) end endend

spec/factories/users.rb

irb(main):001:0> FactoryGirl.create(:user).posts.length=> 0

irb(main):001:0> FactoryGirl.create(:user_with_posts).posts.length=> 5

irb(main):001:0> FactoryGirl.create(:user_with_posts,posts_count: 15).posts.length=> 15

Wrapping Up...

Factory Girl is Magic

Easier to Maintain

Less of a Headache

Fun to Work With

Questions?

top related