Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Factory Girl

Factory Girl

How to use Factory Girl for creating model fakes in your test. Video where I talk over it the whole time: https://vimeo.com/119875543

Ben Kreeger

February 13, 2015
Tweet

More Decks by Ben Kreeger

Other Decks in Programming

Transcript

  1. Summing up a complex human being in two hours is

    like an MTV spot about Nelson Mandela cut to a Kanye West track. 1 Brian Holcomb, CinemaBlend.com 2
  2. Integrate it $ mkdir -p ./spec/support $ vim ./spec/support/factory_girl.rb #

    spec/support/factory_girl.rb RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end 5
  3. Define them $ mkdir -p ./spec/factories $ vim ./spec/factories/user_factories.rb #

    spec/factories/user_factories.rb FactoryGirl.define do factory :user do first_name "Jon" last_name "Snow" is_nights_watch true end end 6
  4. Refine them FactoryGirl.define do factory :user do first_name "Jon" last_name

    "Snow" is_nights_watch true trait(:knows_nothing) do knows [] end end end 7
  5. Relate them FactoryGirl.define do factory :animal do species "Sciurus carolinensis"

    name "squirrel" end factory :direwolf, class: Animal do species "Canis dirus" name "direwolf" end end 8
  6. Relate them FactoryGirl.define do factory :user do first_name "Jon" last_name

    "Snow" is_nights_watch true trait(:knows_nothing) { knows [] } trait(:has_animal) { animal } trait(:has_direwolf) do association :animal, factory: :direwolf end end end 9
  7. Make them saved_instance = FactoryGirl.create(:user) # <User id: 1, first_name:

    "Jon", last_name: "Snow"> non_persisted = FactoryGirl.build(:user) # <User id: nil, first_name: "Jon", last_name: "Snow"> hash = FactoryGirl.attributes_for(:user) # { first_name: "Jon", last_name: "Snow" } If you're using Rspec and have included the FactoryGirl helpers… saved_instance = create(:user) # <User id: 1, first_name: "Jon", last_name: "Snow"> 10
  8. Make them user = create(:user, :knows_nothing, :has_direwolf) # <User id:

    1, first_name: "Jon", last_name: "Snow", knows: []> user.animal # <Animal id: 1, species: "Canis dirus", name: "direwolf"> 11
  9. Make them master_at_arms = create(:user, :has_animal, first_name: "Alliser", last_name: "Thorne")

    # <User id: 1, first_name: "Alliser", last_name: "Thorne"> master_at_arms.animal # <Animal id: 1, species: "Sciurus carolinensis", name: "squirrel"> 12
  10. Child factories with traits factory :user do on_nights_watch false #

    Traits can be cascaded/layered. Last one gets precedence. trait(:nights_watch) { on_nights_watch(true) } trait(:has_direwolf) { direwolf } factory :jon_snow, traits: %i(nights_watch has_direwolf) end # To use... create(:jon_snow) # <User id: 1, name: "Jon Snow", on_nights_watch: true> 15
  11. Lazily-computed attributes factory :user do # Use when your data

    is not static. signed_up_at { 21.seconds.ago } end 16
  12. Sequences factory :user do # To ensure your data is

    unique-ish. sequence(:codename) { |idx| "user-#{idx}" } end 17
  13. Fake things with Faker factory :user do first_name { Faker::Name.first_name

    } email { Faker::Internet.email } bitcoin { Faker::Bitcoin.address } about { Faker::Lorem.paragraph(2).join("\n") } end Make your tests less dependent on specific data. This is a Good Thing™. 18
  14. Dependent attributes factory :user do first_name "Jon" last_name "Snow" #

    This is super simple, but must be lazily-evaluated ygritte_says { "You know nothing, #{first_name} #{last_name}."} end 19
  15. Non-persisted (transient) attributes factory :user do ignored do broke_vows false

    end name "Jon Snow" after_create do |user, factory_instance| if factory_instance.broke_vows user.revoke_nights_watch_status! end end end 20
  16. Batch creation animals = FactoryGirl.create_list(:animal, 25) unsaved_direwolves = FactoryGirl.build_list(:direwolf, 5)

    lannisters = FactoryGirl.create_list(:user, last_name: "Lannister", sigil: "Lion") 22