SlideShare una empresa de Scribd logo
1 de 26
Philly.rb meetup
Rails testing:
factories or
fixtures?
factories or
Michael Toppa
March 11, 2014
@mtoppa
Why use factories or fixtures?
❖ Factories and fixtures can simplify otherwise repetitive and
complex data setup for tests
❖ Your need for them in unit tests will be light if you do TDD
with loosely-coupled code
❖ But they are vital for unit-“ish” testing if you’re working with
tightly coupled code
❖ e.g. most Rails apps, and the examples in this presentation
❖ They are great for integration testing
Comparisons
❖ Tests with no factories or fixtures
❖ Tests with fixtures
❖ Tests with factories, using FactoryGirl
❖ We’ll test the same method in each case, so you can
clearly see the differences
Partial data model for our
examples
CandidateCandidate
(politician)(politician)
RaceRaceCampaignCampaign
OfficeOffice
CurrentCurrent
HoldersHolders
Winning Campaign
Our test case
Tests with no factories or
fixtures
Ok for simple cases
# spec/models/candidate_spec.rb
describe Candidate do
describe "#calculate_completeness" do
it "returns 0 when no fields are filled out" do
toppa = Candidate.new
toppa.calculate_completeness.should eq(0.0)
end
it "returns a ratio of filled-out fields to total fields" do
toppa = Candidate.new
toppa.name = "Mike Toppa"
toppa.facebook_url = "https://facebook/ElJefe"
toppa.wikipedia_url = "http://en.wikipedia.org/wiki/Mike_Toppa"
toppa.calculate_completeness.should eq(0.2) # 3 / 15 = 0.2
end
end
Not so good for complex
cases# spec/models/race_spec.rb
describe Race do
describe '#inaugurate!' do
it 'makes Mike Toppa President of the United States' do
toppa = Candidate.create(
name: 'Mike Toppa',
[and all required attributes]
)
president = Office.create(
title: 'President of the United States',
[and all required attributes]
)
presidential_race = Race.create([president + all req attrs])
toppa_campaign = Campaign.create([toppa + presidential_race + all
req attrs])
presidential_race.winning_campaign = toppa_campaign
presidential_race.inaugurate!
president.current_holders.first.should == toppa
end
end
end
Tests with fixtures
The fixture files
# spec/fixtures/candidates.yml
mike_toppa:
id: 1
name: Mike Toppa
gender: M
[etc…]
# spec/fixtures/office.yml
president:
id: 1
title: President of the United States
level: N
[etc…]
# spec/fixtures/race.yml
president_race_2012:
id: 1
office: president
election_day: 10/4/2012
[etc…]
# spec/fixtures/campaign.yml
toppa_us_president_campaign_2012:
id: 1
race: president_race_2012
candidate: mike_toppa
fec_id: XYZ
The test file
# spec/models/race_spec.rb
describe Race do
describe '#inaugurate!' do
it 'makes Mike Toppa President of the United States' do
toppa = candidates(:mike_toppa)
president = offices(:president)
presidential_race = races(:us_president_race_2012)
toppa_campaign = campaigns(:toppa_us_president_campaign_2012)
presidential_race.winning_campaign = toppa_campaign
presidential_race.inaugurate!
president.current_holders.first.should == toppa
end
end
end
Pros
❖ For simple scenarios, re-usable across tests
❖ Easy to generate from live data
❖ Fixture files are easy to read
❖ Tests are fairly fast
❖ Records are inserted based on the fixture files,
bypassing ActiveRecord
Cons
❖ Brittle
❖ If you add required fields to a model, you have to update
all its fixtures
❖ Fixture files are an external dependency
❖ Fixtures are organized by model - you need to keep track
of their relationships with test scenarios
❖ Not dynamic - you get the same values every time
❖ (this may or may not be ok)
Tests with factories,
using FactoryGirl
using FactoryGirl
The factory files
# spec/factories/candidates.rb
FactoryGirl.define do
factory :candidate do
name 'Jane Doe'
gender 'F'
[etc…]
# spec/factories/offices.rb
FactoryGirl.define do
factory :office do
title 'Senator'
level 'N'
[etc…]
# spec/factories/races.rb
FactoryGirl.define do
factory :race do
office
election_day '11/04/2014'.to_datetime
[etc…]
# spec/factories/campaigns.rb
FactoryGirl.define do
factory :campaign do
candidate
race
fec_id 'XYZ'
The test file
# spec/models/race_spec.rb
describe Race do
describe '#inaugurate!' do
it 'makes Mike Toppa President of the United States' do
toppa = create :candidate, name: 'Mike Toppa'
president = create(
:office,
title: 'President of the United States'
)
presidential_race = create :race, office: president
toppa_campaign = create(
:campaign,
candidate: toppa,
race: presidential_race
)
presidential_race.winning_campaign = toppa_campaign
presidential_race.inaugurate!
president.current_holders.first.should == toppa
end
end
end
But wait, there’s more…
Randomized values with the
Faker gem
# spec/factories/candidates.rb
FactoryGirl.define do
factory :candidate do
name { Faker::Name.name }
wikipedia_url { Faker::Internet.url }
short_bio { Faker::Lorem.paragraph }
phone { Faker::PhoneNumber.phone_number}
address_1 { Faker::Address.street_address }
address_2 { Faker::Address.secondary_address }
city { Faker::Address.city }
state { Faker::Address.state }
zip { Faker::Address.zip_code }
# and other kinds of randomized values
gender { |n| %w[M F].sample }
sequence(:pvs_id)
azavea_updated_at { Time.at(rand * Time.now.to_i) }
[etc…]
Debate on randomized values
❖ Argument for:
❖ Having a wide variety of values, and combinations of values,
in your tests can expose bugs you might otherwise miss
❖ Argument against:
❖ In a test using many different model instances, failures can be
difficult to reproduce and debug
❖ If you’re counting on randomized values to find bugs, your
design process may not be robust
Instantiation options
❖ create: saves your object to the database, and saves
any associated objects to the database
❖ build: builds your object in memory only, but still
saves any associated objects to the database
❖ build_stubbed: builds your object in memory only, as
well as any associated objects
Instantiation options
❖ Use build_stubbed whenever possible - your tests
will be faster!
❖ You will need to use create or build for integration
testing
❖ …and if you’re stuck with tightly coupled Rails code
For frequent scenarios: child
factories
# spec/factories/offices.rb
FactoryGirl.define do
factory :office do
title 'Mayor'
level 'L'
[etc…]
factory :office_president do
status 'A'
title 'President of the United States'
level 'N'
[etc…]
end
end
end
# spec/models/race_spec.rb
describe Race do
describe '#inaugurate!' do
it 'makes Mike Toppa President of the United States' do
president = create :office_president
[etc…]
end
end
end
Child factories using other child
factories
# spec/factories/offices.rb
FactoryGirl.define do
factory :office do
area
title 'Mayor'
level 'L'
[etc…]
factory :office_house do
association :area, factory: :congressional_district
status 'A'
level 'N'
type_code 'H'
[etc…]
end
end
end
For frequent scenarios: traits
# spec/factories/candidates.rb
FactoryGirl.define do
factory :candidate do
name 'Jane Doe'
gender 'F'
[etc…]
end
trait :with_office_house do
after :create do |candidate|
office = create :office_house
create :current_office_holder, :office => office, :candidate => candidate
end
end
end
# spec/models/race_spec.rb
describe Race do
describe '#inaugurate!' do
it 'makes Mike Toppa President of the United States' do
toppa = create: candidate, :with_office_house
[etc…]
end
end
end
Don’t overuse child factories
and traits - leads to brittleness
Factories address shortcomings of
fixtures
❖ Not as brittle
❖ Factory won’t break if you add a new required field to a model
❖ You don’t need to maintain complex scenarios spread out across
fixture files
❖ Lessened external dependency, more flexibility
❖ You can define the attributes important to the test in the test code
itself
❖ When using build_stubbed your tests will be faster
❖ But fixtures are faster when inserting records

Más contenido relacionado

Similar a Rails testing: factories or fixtures?

fixtures_vs_AR_vs_factories.ppt
fixtures_vs_AR_vs_factories.pptfixtures_vs_AR_vs_factories.ppt
fixtures_vs_AR_vs_factories.pptTom Plisskin
 
Oracle APEX for Beginners
Oracle APEX for BeginnersOracle APEX for Beginners
Oracle APEX for BeginnersDimitri Gielis
 
Unit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestUnit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestHosang Jeon
 
Six simple steps to unit testing happiness
Six simple steps to unit testing happinessSix simple steps to unit testing happiness
Six simple steps to unit testing happinessSteven Feuerstein
 
Writing useful automated tests for the single page applications you build
Writing useful automated tests for the single page applications you buildWriting useful automated tests for the single page applications you build
Writing useful automated tests for the single page applications you buildAndrei Sebastian Cîmpean
 
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...DataScienceConferenc1
 
WEBINAR: Proven Patterns for Loading Test Data for Managed Package Testing
WEBINAR: Proven Patterns for Loading Test Data for Managed Package TestingWEBINAR: Proven Patterns for Loading Test Data for Managed Package Testing
WEBINAR: Proven Patterns for Loading Test Data for Managed Package TestingCodeScience
 
Continuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsContinuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsSOASTA
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to KnowVaidas Pilkauskas
 
10 Tips for Configuring Your Builds with Bamboo Specs
10 Tips for Configuring Your Builds with Bamboo Specs10 Tips for Configuring Your Builds with Bamboo Specs
10 Tips for Configuring Your Builds with Bamboo SpecsAtlassian
 
Continuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsContinuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsSOASTA
 
Test automation Frame Works
Test automation Frame WorksTest automation Frame Works
Test automation Frame WorksvodQA
 
An Introduction to Test Driven Development
An Introduction to Test Driven Development An Introduction to Test Driven Development
An Introduction to Test Driven Development CodeOps Technologies LLP
 
CoreData - there is an ORM you can like!
CoreData - there is an ORM you can like!CoreData - there is an ORM you can like!
CoreData - there is an ORM you can like!Tomáš Jukin
 
Implement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlowImplement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlowTechWell
 
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019VMware Tanzu
 
Getting your mobile test automation process in place - using Cucumber and Cal...
Getting your mobile test automation process in place - using Cucumber and Cal...Getting your mobile test automation process in place - using Cucumber and Cal...
Getting your mobile test automation process in place - using Cucumber and Cal...Niels Frydenholm
 
Scaling Ride-Hailing with Machine Learning on MLflow
Scaling Ride-Hailing with Machine Learning on MLflowScaling Ride-Hailing with Machine Learning on MLflow
Scaling Ride-Hailing with Machine Learning on MLflowDatabricks
 

Similar a Rails testing: factories or fixtures? (20)

fixtures_vs_AR_vs_factories.ppt
fixtures_vs_AR_vs_factories.pptfixtures_vs_AR_vs_factories.ppt
fixtures_vs_AR_vs_factories.ppt
 
Testing smells
Testing smellsTesting smells
Testing smells
 
Oracle APEX for Beginners
Oracle APEX for BeginnersOracle APEX for Beginners
Oracle APEX for Beginners
 
Unit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by MinitestUnit Test in Ruby on Rails by Minitest
Unit Test in Ruby on Rails by Minitest
 
Six simple steps to unit testing happiness
Six simple steps to unit testing happinessSix simple steps to unit testing happiness
Six simple steps to unit testing happiness
 
Writing useful automated tests for the single page applications you build
Writing useful automated tests for the single page applications you buildWriting useful automated tests for the single page applications you build
Writing useful automated tests for the single page applications you build
 
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...
[DSC Europe 22] Engineers guide for shepherding models in to production - Mar...
 
WEBINAR: Proven Patterns for Loading Test Data for Managed Package Testing
WEBINAR: Proven Patterns for Loading Test Data for Managed Package TestingWEBINAR: Proven Patterns for Loading Test Data for Managed Package Testing
WEBINAR: Proven Patterns for Loading Test Data for Managed Package Testing
 
Continuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsContinuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and Jenkins
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to Know
 
10 Tips for Configuring Your Builds with Bamboo Specs
10 Tips for Configuring Your Builds with Bamboo Specs10 Tips for Configuring Your Builds with Bamboo Specs
10 Tips for Configuring Your Builds with Bamboo Specs
 
Continuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and JenkinsContinuous Load Testing with CloudTest and Jenkins
Continuous Load Testing with CloudTest and Jenkins
 
Test automation Frame Works
Test automation Frame WorksTest automation Frame Works
Test automation Frame Works
 
An Introduction to Test Driven Development
An Introduction to Test Driven Development An Introduction to Test Driven Development
An Introduction to Test Driven Development
 
CoreData - there is an ORM you can like!
CoreData - there is an ORM you can like!CoreData - there is an ORM you can like!
CoreData - there is an ORM you can like!
 
Implement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlowImplement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlow
 
Defensive Apex Programming
Defensive Apex ProgrammingDefensive Apex Programming
Defensive Apex Programming
 
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019
Agile Data Science on Greenplum Using Airflow - Greenplum Summit 2019
 
Getting your mobile test automation process in place - using Cucumber and Cal...
Getting your mobile test automation process in place - using Cucumber and Cal...Getting your mobile test automation process in place - using Cucumber and Cal...
Getting your mobile test automation process in place - using Cucumber and Cal...
 
Scaling Ride-Hailing with Machine Learning on MLflow
Scaling Ride-Hailing with Machine Learning on MLflowScaling Ride-Hailing with Machine Learning on MLflow
Scaling Ride-Hailing with Machine Learning on MLflow
 

Más de mtoppa

RubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againRubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againmtoppa
 
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot WayRailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot Waymtoppa
 
Applying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workApplying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workmtoppa
 
Talking to strangers causes train wrecks
Talking to strangers causes train wrecksTalking to strangers causes train wrecks
Talking to strangers causes train wrecksmtoppa
 
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...mtoppa
 
The promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesThe promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesmtoppa
 
Why do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersWhy do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersmtoppa
 
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesBoston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesmtoppa
 
A real-life overview of Agile and Scrum
A real-life overview of Agile and ScrumA real-life overview of Agile and Scrum
A real-life overview of Agile and Scrummtoppa
 
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesWordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesmtoppa
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Codemtoppa
 
Dependency Injection for PHP
Dependency Injection for PHPDependency Injection for PHP
Dependency Injection for PHPmtoppa
 
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress ConsultantsWordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress Consultantsmtoppa
 
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress ConsultantsWordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress Consultantsmtoppa
 
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?mtoppa
 
WordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressWordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressmtoppa
 
A real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesA real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesmtoppa
 
Why Agile? Why Now?
Why Agile? Why Now?Why Agile? Why Now?
Why Agile? Why Now?mtoppa
 
Object Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin DevelopmentObject Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin Developmentmtoppa
 
Dependency Injection for Wordpress
Dependency Injection for WordpressDependency Injection for Wordpress
Dependency Injection for Wordpressmtoppa
 

Más de mtoppa (20)

RubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back againRubyConf 2022 - From beginner to expert, and back again
RubyConf 2022 - From beginner to expert, and back again
 
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot WayRailsConf 2022 - Upgrading Rails: The Dual Boot Way
RailsConf 2022 - Upgrading Rails: The Dual Boot Way
 
Applying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your workApplying Omotenashi (Japanese customer service) to your work
Applying Omotenashi (Japanese customer service) to your work
 
Talking to strangers causes train wrecks
Talking to strangers causes train wrecksTalking to strangers causes train wrecks
Talking to strangers causes train wrecks
 
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between:  accessib...
A11Y? I18N? L10N? UTF8? WTF? Understanding the connections between: accessib...
 
The promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practicesThe promise and peril of Agile and Lean practices
The promise and peril of Agile and Lean practices
 
Why do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developersWhy do planes crash? Lessons for junior and senior developers
Why do planes crash? Lessons for junior and senior developers
 
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practicesBoston Ruby Meetup: The promise and peril of Agile and Lean practices
Boston Ruby Meetup: The promise and peril of Agile and Lean practices
 
A real-life overview of Agile and Scrum
A real-life overview of Agile and ScrumA real-life overview of Agile and Scrum
A real-life overview of Agile and Scrum
 
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practicesWordCamp Nashville 2016: The promise and peril of Agile and Lean practices
WordCamp Nashville 2016: The promise and peril of Agile and Lean practices
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Code
 
Dependency Injection for PHP
Dependency Injection for PHPDependency Injection for PHP
Dependency Injection for PHP
 
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress ConsultantsWordCamp Boston 2015: Agile Contracts for WordPress Consultants
WordCamp Boston 2015: Agile Contracts for WordPress Consultants
 
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress ConsultantsWordCamp Nashville 2015: Agile Contracts for WordPress Consultants
WordCamp Nashville 2015: Agile Contracts for WordPress Consultants
 
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
WordCamp Lancaster 2014: A11Y? I18N? L10N? UTF8? WTF?
 
WordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPressWordCamp Nashville: Clean Code for WordPress
WordCamp Nashville: Clean Code for WordPress
 
A real-life overview of Agile workflow practices
A real-life overview of Agile workflow practicesA real-life overview of Agile workflow practices
A real-life overview of Agile workflow practices
 
Why Agile? Why Now?
Why Agile? Why Now?Why Agile? Why Now?
Why Agile? Why Now?
 
Object Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin DevelopmentObject Oriented Programming for WordPress Plugin Development
Object Oriented Programming for WordPress Plugin Development
 
Dependency Injection for Wordpress
Dependency Injection for WordpressDependency Injection for Wordpress
Dependency Injection for Wordpress
 

Último

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 

Último (20)

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

Rails testing: factories or fixtures?

  • 1. Philly.rb meetup Rails testing: factories or fixtures? factories or Michael Toppa March 11, 2014 @mtoppa
  • 2. Why use factories or fixtures? ❖ Factories and fixtures can simplify otherwise repetitive and complex data setup for tests ❖ Your need for them in unit tests will be light if you do TDD with loosely-coupled code ❖ But they are vital for unit-“ish” testing if you’re working with tightly coupled code ❖ e.g. most Rails apps, and the examples in this presentation ❖ They are great for integration testing
  • 3. Comparisons ❖ Tests with no factories or fixtures ❖ Tests with fixtures ❖ Tests with factories, using FactoryGirl ❖ We’ll test the same method in each case, so you can clearly see the differences
  • 4. Partial data model for our examples CandidateCandidate (politician)(politician) RaceRaceCampaignCampaign OfficeOffice CurrentCurrent HoldersHolders Winning Campaign
  • 6. Tests with no factories or fixtures
  • 7. Ok for simple cases # spec/models/candidate_spec.rb describe Candidate do describe "#calculate_completeness" do it "returns 0 when no fields are filled out" do toppa = Candidate.new toppa.calculate_completeness.should eq(0.0) end it "returns a ratio of filled-out fields to total fields" do toppa = Candidate.new toppa.name = "Mike Toppa" toppa.facebook_url = "https://facebook/ElJefe" toppa.wikipedia_url = "http://en.wikipedia.org/wiki/Mike_Toppa" toppa.calculate_completeness.should eq(0.2) # 3 / 15 = 0.2 end end
  • 8. Not so good for complex cases# spec/models/race_spec.rb describe Race do describe '#inaugurate!' do it 'makes Mike Toppa President of the United States' do toppa = Candidate.create( name: 'Mike Toppa', [and all required attributes] ) president = Office.create( title: 'President of the United States', [and all required attributes] ) presidential_race = Race.create([president + all req attrs]) toppa_campaign = Campaign.create([toppa + presidential_race + all req attrs]) presidential_race.winning_campaign = toppa_campaign presidential_race.inaugurate! president.current_holders.first.should == toppa end end end
  • 10. The fixture files # spec/fixtures/candidates.yml mike_toppa: id: 1 name: Mike Toppa gender: M [etc…] # spec/fixtures/office.yml president: id: 1 title: President of the United States level: N [etc…] # spec/fixtures/race.yml president_race_2012: id: 1 office: president election_day: 10/4/2012 [etc…] # spec/fixtures/campaign.yml toppa_us_president_campaign_2012: id: 1 race: president_race_2012 candidate: mike_toppa fec_id: XYZ
  • 11. The test file # spec/models/race_spec.rb describe Race do describe '#inaugurate!' do it 'makes Mike Toppa President of the United States' do toppa = candidates(:mike_toppa) president = offices(:president) presidential_race = races(:us_president_race_2012) toppa_campaign = campaigns(:toppa_us_president_campaign_2012) presidential_race.winning_campaign = toppa_campaign presidential_race.inaugurate! president.current_holders.first.should == toppa end end end
  • 12. Pros ❖ For simple scenarios, re-usable across tests ❖ Easy to generate from live data ❖ Fixture files are easy to read ❖ Tests are fairly fast ❖ Records are inserted based on the fixture files, bypassing ActiveRecord
  • 13. Cons ❖ Brittle ❖ If you add required fields to a model, you have to update all its fixtures ❖ Fixture files are an external dependency ❖ Fixtures are organized by model - you need to keep track of their relationships with test scenarios ❖ Not dynamic - you get the same values every time ❖ (this may or may not be ok)
  • 14. Tests with factories, using FactoryGirl using FactoryGirl
  • 15. The factory files # spec/factories/candidates.rb FactoryGirl.define do factory :candidate do name 'Jane Doe' gender 'F' [etc…] # spec/factories/offices.rb FactoryGirl.define do factory :office do title 'Senator' level 'N' [etc…] # spec/factories/races.rb FactoryGirl.define do factory :race do office election_day '11/04/2014'.to_datetime [etc…] # spec/factories/campaigns.rb FactoryGirl.define do factory :campaign do candidate race fec_id 'XYZ'
  • 16. The test file # spec/models/race_spec.rb describe Race do describe '#inaugurate!' do it 'makes Mike Toppa President of the United States' do toppa = create :candidate, name: 'Mike Toppa' president = create( :office, title: 'President of the United States' ) presidential_race = create :race, office: president toppa_campaign = create( :campaign, candidate: toppa, race: presidential_race ) presidential_race.winning_campaign = toppa_campaign presidential_race.inaugurate! president.current_holders.first.should == toppa end end end
  • 18. Randomized values with the Faker gem # spec/factories/candidates.rb FactoryGirl.define do factory :candidate do name { Faker::Name.name } wikipedia_url { Faker::Internet.url } short_bio { Faker::Lorem.paragraph } phone { Faker::PhoneNumber.phone_number} address_1 { Faker::Address.street_address } address_2 { Faker::Address.secondary_address } city { Faker::Address.city } state { Faker::Address.state } zip { Faker::Address.zip_code } # and other kinds of randomized values gender { |n| %w[M F].sample } sequence(:pvs_id) azavea_updated_at { Time.at(rand * Time.now.to_i) } [etc…]
  • 19. Debate on randomized values ❖ Argument for: ❖ Having a wide variety of values, and combinations of values, in your tests can expose bugs you might otherwise miss ❖ Argument against: ❖ In a test using many different model instances, failures can be difficult to reproduce and debug ❖ If you’re counting on randomized values to find bugs, your design process may not be robust
  • 20. Instantiation options ❖ create: saves your object to the database, and saves any associated objects to the database ❖ build: builds your object in memory only, but still saves any associated objects to the database ❖ build_stubbed: builds your object in memory only, as well as any associated objects
  • 21. Instantiation options ❖ Use build_stubbed whenever possible - your tests will be faster! ❖ You will need to use create or build for integration testing ❖ …and if you’re stuck with tightly coupled Rails code
  • 22. For frequent scenarios: child factories # spec/factories/offices.rb FactoryGirl.define do factory :office do title 'Mayor' level 'L' [etc…] factory :office_president do status 'A' title 'President of the United States' level 'N' [etc…] end end end # spec/models/race_spec.rb describe Race do describe '#inaugurate!' do it 'makes Mike Toppa President of the United States' do president = create :office_president [etc…] end end end
  • 23. Child factories using other child factories # spec/factories/offices.rb FactoryGirl.define do factory :office do area title 'Mayor' level 'L' [etc…] factory :office_house do association :area, factory: :congressional_district status 'A' level 'N' type_code 'H' [etc…] end end end
  • 24. For frequent scenarios: traits # spec/factories/candidates.rb FactoryGirl.define do factory :candidate do name 'Jane Doe' gender 'F' [etc…] end trait :with_office_house do after :create do |candidate| office = create :office_house create :current_office_holder, :office => office, :candidate => candidate end end end # spec/models/race_spec.rb describe Race do describe '#inaugurate!' do it 'makes Mike Toppa President of the United States' do toppa = create: candidate, :with_office_house [etc…] end end end
  • 25. Don’t overuse child factories and traits - leads to brittleness
  • 26. Factories address shortcomings of fixtures ❖ Not as brittle ❖ Factory won’t break if you add a new required field to a model ❖ You don’t need to maintain complex scenarios spread out across fixture files ❖ Lessened external dependency, more flexibility ❖ You can define the attributes important to the test in the test code itself ❖ When using build_stubbed your tests will be faster ❖ But fixtures are faster when inserting records

Notas del editor

  1. Introductions to using tools usually have overly-simple examples. We’re going to use more realistic examples, as you can only get a feel for the differences between factories and fixtures when dealing with more complex scenarios.
  2. The method we’ll examine is for inaugurating a new office holder, and we’ll make me President of the United States
  3. Fast, simple, clear (not hitting the database)
  4. Specifying all the attributes is cumbersome and when reading the test, distracts from understanding the purpose of the test Brittle: if add a required field to a model, you have to update all the tests using that model Hard to reuse
  5. For each model’s fixture file, you can have multiple records defined updated_at and created_at are set automatically with the current time, or you can specify them
  6. A simple factory file can look a lot like a fixture file…
  7. … but a key difference is that you can override values and specify associations when writing the test