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

Using Factories (or not)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Using Factories (or not)

Using Factories via FactoryBot

Avatar for Stephanie Viccari

Stephanie Viccari

January 05, 2021

More Decks by Stephanie Viccari

Other Decks in Education

Transcript

  1. TMI describe "#full_title" do it "combines the title and subtitle"

    do book = Book.new(title: "POODR", subtitle: "An Agile Primer", publication_year: 2012) expect(book.full_title).to eq "POODR: An Agile Primer" end end 4
  2. TMI describe "#full_title" do it "combines the title and subtitle"

    do book = Book.new(title: "POODR", subtitle: "An Agile Primer", publication_year: 2012) expect(book.full_title).to eq "POODR: An Agile Primer" end end 5
  3. Too little info describe "#full_title" do it "combines the title

    and subtitle" do expect(example_book.full_title).to eq "POODR: An Agile Primer" end end 6
  4. Just Right describe "#full_title" do it "combines the title and

    subtitle" do book = Book.new(title: "POODR", subtitle: "An Agile Primer") expect(book.full_title).to eq "POODR: An Agile Primer" end end 7
  5. Handling required fields class Book < ApplicationRecord validates :title, presence:

    true validates :subtitle, presence: true validates :publication_year, presence: true end describe "#full_title" do it "combines the title and subtitle" do # Invalid book = Book.new(title: "POODR", subtitle: "An Agile Primer") expect(book.full_title).to eq "POODR: An Agile Primer" end end 8
  6. Enter the factory method pattern • Minimize mystery guests •

    Include all data that impacts expectation • Include no data that doesn't impact expectation # books_factory.rb factory :book do title { "default" } subtitle { "default" } publication_year { 2018 } end # book_spec.rb it "has a publication year" do book = FactoryBot.build_stubbed( :book, title: "POODR", subtitle: "An Agile Primer" ) expect(book.publication_year).to eq 2018 end 9
  7. Why not use factories? • Easy to hide slow operations

    • Changes to factories have cascading effects • It can be slower than building an object directly # books_factory.rb factory :book do title { "default" } subtitle { "default" } publication_year { 2018 } author end factory :author 10
  8. Do I need a factory? • Do I need the

    db? • Do I need associations? • Do I need a lot of data to test this operation? If not, I might not need a factory. describe "#full_title" do it "combines the title and subtitle" do book = Book.new(title: "POODR", subtitle: "An Agile Primer") expect(book.full_title).to eq "POODR: An Agile Primer" end end 12
  9. Which creation method do I need? • build • create

    • build_stubbed • attributes_for # Return an unsaved book instance book = build(:book) # Return a saved book instance book = create(:book) # return an object with all defined attributes stubbed out stub = build_stubbed(:book) # return a hash of attributes that can be used to build a book instance attributes = attributes_for(:book) 13
  10. Which creation method do I need? • build • create

    • build_stubbed • attributes_for # Return an unsaved book instance book = build(:book) # Return a saved book instance book = create(:book) # return an object with all defined attributes stubbed out stub = build_stubbed(:book) # return a hash of attributes that can be used to build a book instance attributes = attributes_for(:book) 14
  11. What info should I include in my factory? • As

    little as possible! • Mirror validations • Use traits for everything else 15
  12. What info should I include in my factory? factory :author

    do name { "Chloe Ardelia Wofford" } pen_name { "Toni Morrison" } after(:create) do |author| create(:book, author: author) end end create(:author).pen_name # Toni Morrison create(:author).book.title # The Bluest Eye 16
  13. What info should I include in my factory? factory :author

    do name { "Chloe Ardelia Wofford" } pen_name { "Toni Morrison" } after(:create) do |author| create(:book, author: author) end end create(:author).pen_name # Toni Morrison create(:author).book.title # The Bluest Eye 17
  14. Named Factories Using Traits factory :author do name { "Chloe

    Ardelia Wofford" } trait :with_pen_name do pen_name { "Toni Morrison" } end trait :with_book do after(:create) do |author| create(:book, author: author) end end factory :author_with_pen_name, traits: [:with_pen_name] factory :author_with_book, traits: [:with_book] factory :author_with_pen_name_and_book, traits: [:with_pen_name, :with_book] end create(:author).pen_name # nil create(:author).book # nil create(:author_with_pen_name) # "Toni Morrison" create(:author_with_book).book.title # "The Bluest Eye" 18
  15. Named Factories Using Traits factory :author do name { "Chloe

    Ardelia Wofford" } trait :with_pen_name do pen_name { "Toni Morrison" } end trait :with_book do after(:create) do |author| create(:book, author: author) end end factory :author_with_pen_name, traits: [:with_pen_name] factory :author_with_book, traits: [:with_book] factory :author_with_pen_name_and_book, traits: [:with_pen_name, :with_book] end create(:author).pen_name # nil create(:author).book # nil create(:author_with_pen_name) # "Toni Morrison" create(:author_with_book).book.title # "The Bluest Eye" 19
  16. "Mixed-in" Traits factory :author do name { "Chloe Ardelia Wofford"

    } trait :with_pen_name do pen_name { "Toni Morrison" } end trait :with_book do after(:create) do |author| create(:book, author: author) end end end create(:author).pen_name # nil create(:author).book # nil create(:author, :with_pen_name).pen_name # "Toni Morrison" create(:author, :with_book).book.title # "The Bluest Eye" create(:author, :with_pen_name, :with_book).book.title # "The Bluest Eye" create(:author, :with_pen_name, :with_book).pen_name # "Toni Morrison" 20
  17. "Mixed-in" Traits factory :author do name { "Chloe Ardelia Wofford"

    } trait :with_pen_name do pen_name { "Toni Morrison" } end trait :with_book do after(:create) do |author| create(:book, author: author) end end end create(:author).pen_name # nil create(:author).book # nil create(:author, :with_pen_name).pen_name # "Toni Morrison" create(:author, :with_book).book.title # "The Bluest Eye" create(:author, :with_pen_name, :with_book).book.title # "The Bluest Eye" create(:author, :with_pen_name, :with_book).pen_name # "Toni Morrison" 21
  18. Resources Why Factories - https://thoughtbot.com/blog/why-factories Factories should be the bare

    minimum - https://thoughtbot.com/blog/factories- should-be-the-bare-minimum Speed up tests by selectively avoiding FactoryBot - https://thoughtbot.com/blog/speed-up-tests- by-selectively-avoiding-factory-girl Remove duplication with FactoryBot's traits - https://thoughtbot.com/blog/remove- duplication-with-factorygirls-traits 22