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

Using Factories (or not)

Using Factories (or not)

Using Factories via FactoryBot

Stephanie Viccari

January 05, 2021
Tweet

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