SlideShare une entreprise Scribd logo
1  sur  35
Télécharger pour lire hors ligne
DOUBLETROUBLE
Clarity on test doubles.
TESTING PHASES
exercise
verify
teardown
let(:sox) { Team.new “Boston” }
let(:drays) { Team.new “Tampa” }
before { sox.play(drays) }
it “should set standings” do
expect(drays).to be_losing
end
after { standings.delete_all }
setup
TESTING PHASES
setup
exercise
verify
teardown
→
let(:sox) { Team.new “Boston” }
let(:drays) { Team.new “Tampa” }
before { sox.play(drays) }
it “should set standings” do
expect(drays).to be_losing
end
after { standings.delete_all }
TESTING PHASES
excercise
setup
verify
teardown
→
let(:sox) { Team.new “Boston” }
let(:drays) { Team.new “Tampa” }
before { sox.play(drays) }
it “should set standings” do
expect(drays).to be_losing
end
after { standings.delete_all }
TESTING PHASES
verify
setup
exercise
teardown
→
let(:sox) { Team.new “Boston” }
let(:drays) { Team.new “Tampa” }
before { sox.play(drays) }
it “should set standings” do
expect(drays).to be_losing
end
after { standings.delete_all }
TESTING PHASES
teardown
setup
exercise
verify
→
let(:sox) { Team.new “Boston” }
let(:drays) { Team.new “Tampa” }
before { sox.play(drays) }
it “should set standings” do
expect(drays).to be_losing
end
after { standings.delete_all }
WHAT IS ATEST DOUBLE?
WHAT IS ATEST DOUBLE?
SUT
DOC
WHAT IS ATEST DOUBLE?
SUT
DOC
WHAT IS ATEST DOUBLE?
SUT
Indirect Output
DOC
WHAT IS ATEST DOUBLE?
SUT
Indirect Output
Indirect Input
DOCTest
Double
WHAT IS ATEST DOUBLE?
SUT
Indirect Output
Indirect Input
TEST DOUBLE PATTERNS
• Dummy Object
• Fake Object
• Mock Object
• Test Stub
• Test Spy
DUMMY OBJECT
A placeholder that is passed to the SUT and never used
let(:side_a) { 1 }
let(:side_b) { 2 }
let(:dummy) { Object.new }
subject { HighSchoolTrig.hypotenuse(a, b, dummy) }
it { should eq 2.236 }
FAKE OBJECT
An object which replaces the real DOC with an alternate
implementation of the same functionality
class FakePiCalc
def pi; 3.14159; end
end
let(:radius) { 2 }
before { MyGeo.pi_calculator = FakePiCalc }
subject { MyGeo.circumference(radius) }
it { should eq 13 }
MOCKS, STUBS & SPIES
An example:
class User < ActiveRecord::Base
before_create :enqueue_welcome_message
def enqueue_welcome_message
queue = Application.config.email_queue
raise(“Failed to queue”) unless queue.push(email, “Welcome”)
end
end
NO DOUBLES
let(:email) { “tom@crui.se” }
subject { User.create(email: email) }
it { should be_persisted }
its(:username) { should eq email }
MOCK OBJECT
An object which replaces the real DOC that can verify indirect
output from the SUT with expectations
let(:mock_queue) { double() }
let(:email) { “tom@crui.se” }
before do
Application.config.email_queue = mock_queue
expect(mock_queue).to receive(:push).with(email, “Welcome”)
end
subject { User.create(email: email) }
it { should be_persisted }
its(:username) { should eq email }
TEST STUB
An object which replaces the real DOC to control indirect
input to the SUT
let(:stub_queue) { double(push: true) }
let(:email) { “tom@crui.se” }
before do
Application.config.email_queue = stub_queue
end
subject { User.create(email: email) }
it { should be_persisted }
its(:username) { should eq email }
TEST SPY
A more capableTest Stub allowing verification of indirect output
from the SUT
let(:spy_queue) { double(push: true) }
let(:email) { “tom@crui.se” }
before do
Application.config.email_queue = spy_queue
end
subject { User.create(email: email) }
it { should be_persisted }
its(:username) { should eq email }
it “should enqueue welcome message” do
expect(spy_queue).to have_received(:push).with(email, “Ohai”)
end
DESIGNING FOR DOUBLES
• Dependency Lookup
• Dependency Injection
class Buddy
def good_friend?; on_tap.craft?; end
def on_tap
Fridge.cold_one
end
end
describe Buddy, “serving coors” do
# TODO control indirect input to the SUT
it “should not be a good friend” do
expect(subject).not_to be_good_friend
end
DEPENDENCY LOOKUP
class Buddy
def good_friend?; on_tap.craft?; end
def on_tap
Fridge.cold_one
end
end
describe Buddy, “serving coors” do
let(:coors) { double(craft?: false) }
before { Fridge.stubs(:cold_one) { coors } }
it “should not be a good friend” do
expect(subject).not_to be_good_friend
end
class Buddy
attr_accessor :fridge
def good_friend?; on_tap.craft?; end
def on_tap
@fridge.cold_one
end
end
describe Buddy, “serving coors” do
let(:coors) { double(craft?: false) }
let(:stub_fridge) { double(cold_one: coors) }
before { subject.fridge = stub_fridge }
it “should not be a good friend” do
expect(subject).not_to be_good_friend
end
DEPENDENCY INJECTION
RETROFITTING
• Test-Specific Subclasses
• Test Hooks
class Buddy
attr_reader :supermarket
def make_breakfast(request=“Steak & eggs”)
ingredients = supermarket.find(request)
prepare(ingredients)
end
end
TEST-SPECIFIC SUBCLASSES
class Buddy
attr_reader :supermarket
def make_breakfast(request=“Steak & eggs”)
ingredients = supermarket.find(request)
prepare(ingredients)
end
end
class TestBuddy < Buddy
attr_writer :supermarket
end
TEST HOOKS
class Buddy
if ENV != “TEST”
attr_reader :supermarket
else
attr_accessor :supermarket
end
def make_breakfast(request=“Steak & eggs”)
ingredients = supermarket.find(request)
prepare(ingredients)
end
end
ARETHEY FORYOU?
“MOCKIST”TDD / BDD
• Uses mocks for all DOCs
• Likes the test writing process to inform design decisions
• Tests in strict isolation
CLASSICTDD
• Uses test doubles only for awkward DOCs, favoring “real”
objects
• Minimizes coupling between tests and implementation
• Tests small clusters of components, not isolated units
CLASSICTDDERS CONSIDER
USING ATEST DOUBLE IF:
• The behavior of the DOC cannot be changed/observed
• Use of the DOC could cause unwanted side-effects
• The DOC is too slow
• The DOC doesn’t exist yet
OVERUSE CAN LEADTO:
• Over specified tests of the SUT’s process, not its result
• Fragile tests that break when implementation changes
• Untested integration
• Less time on Hacker News while your build runs
MORE
xUnit Test Patterns: xunitpatterns.com
Mocks aren’t Stubs by Martin Fowler: martinfowler.com/articles/mocksArentStubs.html
A case against a case against mocking and stubbing by David Chelimsky:
blog.davidchelimsky.net/2008/12/11/a-case-against-a-case-against-mocking-and-stubbing/
Timecop for testing time-dependent code: github.com/travisjeffery/timecop
RSpec: rspec.info
MiniTest: ruby-doc.org/stdlib
Mocha: github.com/freerange/mocha
greg@promptworks.com

Contenu connexe

Tendances

SilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringSilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringIngo Schommer
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testingjeresig
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 

Tendances (6)

Clean Test Code
Clean Test CodeClean Test Code
Clean Test Code
 
SilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript RefactoringSilverStripe CMS JavaScript Refactoring
SilverStripe CMS JavaScript Refactoring
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
 
Django
Django Django
Django
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 

En vedette

Breakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandBreakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandTiina Sarisalmi
 
School Presentation Szkoła Podstawowa nr 6 im. Janusza Korczaka
School Presentation Szkoła Podstawowa nr 6 im. Janusza KorczakaSchool Presentation Szkoła Podstawowa nr 6 im. Janusza Korczaka
School Presentation Szkoła Podstawowa nr 6 im. Janusza KorczakaTiina Sarisalmi
 
Copyright: Regional Campuses and Distance Education
Copyright: Regional Campuses and Distance EducationCopyright: Regional Campuses and Distance Education
Copyright: Regional Campuses and Distance EducationBritt Fagerheim
 
Change history with Git
Change history with GitChange history with Git
Change history with Gitgsterndale
 
Como subir una actividad o tarea a moodle
Como subir una actividad o tarea a moodleComo subir una actividad o tarea a moodle
Como subir una actividad o tarea a moodleJose Ramirez
 
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”Tiina Sarisalmi
 
Library As Teaching Resource
Library As Teaching ResourceLibrary As Teaching Resource
Library As Teaching ResourceBritt Fagerheim
 
Quarterly Earnings Samsung
Quarterly Earnings SamsungQuarterly Earnings Samsung
Quarterly Earnings Samsungaudrdcos
 
Personagraph Whitepaper
Personagraph WhitepaperPersonagraph Whitepaper
Personagraph WhitepaperTapan Kamdar
 
SEO pro manažery
SEO pro manažerySEO pro manažery
SEO pro manažeryvaclav.lohr
 
Prove Viderekommen
Prove   ViderekommenProve   Viderekommen
Prove Viderekommenguest8e448c
 

En vedette (20)

Breakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from ScotlandBreakfast and Lunch Recipes from Scotland
Breakfast and Lunch Recipes from Scotland
 
School Presentation Szkoła Podstawowa nr 6 im. Janusza Korczaka
School Presentation Szkoła Podstawowa nr 6 im. Janusza KorczakaSchool Presentation Szkoła Podstawowa nr 6 im. Janusza Korczaka
School Presentation Szkoła Podstawowa nr 6 im. Janusza Korczaka
 
Copyright: Regional Campuses and Distance Education
Copyright: Regional Campuses and Distance EducationCopyright: Regional Campuses and Distance Education
Copyright: Regional Campuses and Distance Education
 
Orivesi Countryside
Orivesi CountrysideOrivesi Countryside
Orivesi Countryside
 
Change history with Git
Change history with GitChange history with Git
Change history with Git
 
Our School in Turkey
Our School in TurkeyOur School in Turkey
Our School in Turkey
 
Como subir una actividad o tarea a moodle
Como subir una actividad o tarea a moodleComo subir una actividad o tarea a moodle
Como subir una actividad o tarea a moodle
 
What WELD does
What WELD doesWhat WELD does
What WELD does
 
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”
School Presentation Scuola Statale 5° Circolo Didattico “G. Verdi”
 
Third comeback report 4.8,2011
Third comeback report 4.8,2011Third comeback report 4.8,2011
Third comeback report 4.8,2011
 
Cucumber
CucumberCucumber
Cucumber
 
Library As Teaching Resource
Library As Teaching ResourceLibrary As Teaching Resource
Library As Teaching Resource
 
Quarterly Earnings Samsung
Quarterly Earnings SamsungQuarterly Earnings Samsung
Quarterly Earnings Samsung
 
Personagraph Whitepaper
Personagraph WhitepaperPersonagraph Whitepaper
Personagraph Whitepaper
 
Lugares
LugaresLugares
Lugares
 
The vmware story
The vmware storyThe vmware story
The vmware story
 
Relief 2.0, B2B and Enterprise
Relief 2.0, B2B and EnterpriseRelief 2.0, B2B and Enterprise
Relief 2.0, B2B and Enterprise
 
SEO pro manažery
SEO pro manažerySEO pro manažery
SEO pro manažery
 
Kort Om Etikk2
Kort Om Etikk2Kort Om Etikk2
Kort Om Etikk2
 
Prove Viderekommen
Prove   ViderekommenProve   Viderekommen
Prove Viderekommen
 

Similaire à Double Trouble

Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresiMasters
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescriptDavid Furber
 
Curso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaCurso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaAlberto Perdomo
 
Iterative architecture
Iterative architectureIterative architecture
Iterative architectureJoshuaRizzo4
 
Pytest: escreva menos, teste mais
Pytest: escreva menos, teste maisPytest: escreva menos, teste mais
Pytest: escreva menos, teste maisErick Wilder
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Colin Oakley
 
Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeTed Vinke
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebChristian Baranowski
 
using python module: doctest
using python module: doctestusing python module: doctest
using python module: doctestmitnk
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick IntroductionDamian Jureczko
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wildJoe Morgan
 

Similaire à Double Trouble (20)

Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
The hitchhicker’s guide to unit testing
The hitchhicker’s guide to unit testingThe hitchhicker’s guide to unit testing
The hitchhicker’s guide to unit testing
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
 
Curso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaCurso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: Shoulda
 
Iterative architecture
Iterative architectureIterative architecture
Iterative architecture
 
Pytest: escreva menos, teste mais
Pytest: escreva menos, teste maisPytest: escreva menos, teste mais
Pytest: escreva menos, teste mais
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017
 
groovy & grails - lecture 12
groovy & grails - lecture 12groovy & grails - lecture 12
groovy & grails - lecture 12
 
Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted Vinke
 
Go testdeep
Go testdeepGo testdeep
Go testdeep
 
Groovy Basics
Groovy BasicsGroovy Basics
Groovy Basics
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
using python module: doctest
using python module: doctestusing python module: doctest
using python module: doctest
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
 
Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9
 

Dernier

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
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
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
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
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
 
[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
 
🐬 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
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 

Dernier (20)

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...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
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
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
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
 
[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
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

Double Trouble

  • 2. TESTING PHASES exercise verify teardown let(:sox) { Team.new “Boston” } let(:drays) { Team.new “Tampa” } before { sox.play(drays) } it “should set standings” do expect(drays).to be_losing end after { standings.delete_all } setup
  • 3. TESTING PHASES setup exercise verify teardown → let(:sox) { Team.new “Boston” } let(:drays) { Team.new “Tampa” } before { sox.play(drays) } it “should set standings” do expect(drays).to be_losing end after { standings.delete_all }
  • 4. TESTING PHASES excercise setup verify teardown → let(:sox) { Team.new “Boston” } let(:drays) { Team.new “Tampa” } before { sox.play(drays) } it “should set standings” do expect(drays).to be_losing end after { standings.delete_all }
  • 5. TESTING PHASES verify setup exercise teardown → let(:sox) { Team.new “Boston” } let(:drays) { Team.new “Tampa” } before { sox.play(drays) } it “should set standings” do expect(drays).to be_losing end after { standings.delete_all }
  • 6. TESTING PHASES teardown setup exercise verify → let(:sox) { Team.new “Boston” } let(:drays) { Team.new “Tampa” } before { sox.play(drays) } it “should set standings” do expect(drays).to be_losing end after { standings.delete_all }
  • 7. WHAT IS ATEST DOUBLE?
  • 8. WHAT IS ATEST DOUBLE? SUT
  • 9. DOC WHAT IS ATEST DOUBLE? SUT
  • 10. DOC WHAT IS ATEST DOUBLE? SUT Indirect Output
  • 11. DOC WHAT IS ATEST DOUBLE? SUT Indirect Output Indirect Input
  • 12. DOCTest Double WHAT IS ATEST DOUBLE? SUT Indirect Output Indirect Input
  • 13. TEST DOUBLE PATTERNS • Dummy Object • Fake Object • Mock Object • Test Stub • Test Spy
  • 14. DUMMY OBJECT A placeholder that is passed to the SUT and never used let(:side_a) { 1 } let(:side_b) { 2 } let(:dummy) { Object.new } subject { HighSchoolTrig.hypotenuse(a, b, dummy) } it { should eq 2.236 }
  • 15. FAKE OBJECT An object which replaces the real DOC with an alternate implementation of the same functionality class FakePiCalc def pi; 3.14159; end end let(:radius) { 2 } before { MyGeo.pi_calculator = FakePiCalc } subject { MyGeo.circumference(radius) } it { should eq 13 }
  • 16. MOCKS, STUBS & SPIES An example: class User < ActiveRecord::Base before_create :enqueue_welcome_message def enqueue_welcome_message queue = Application.config.email_queue raise(“Failed to queue”) unless queue.push(email, “Welcome”) end end
  • 17. NO DOUBLES let(:email) { “tom@crui.se” } subject { User.create(email: email) } it { should be_persisted } its(:username) { should eq email }
  • 18. MOCK OBJECT An object which replaces the real DOC that can verify indirect output from the SUT with expectations let(:mock_queue) { double() } let(:email) { “tom@crui.se” } before do Application.config.email_queue = mock_queue expect(mock_queue).to receive(:push).with(email, “Welcome”) end subject { User.create(email: email) } it { should be_persisted } its(:username) { should eq email }
  • 19. TEST STUB An object which replaces the real DOC to control indirect input to the SUT let(:stub_queue) { double(push: true) } let(:email) { “tom@crui.se” } before do Application.config.email_queue = stub_queue end subject { User.create(email: email) } it { should be_persisted } its(:username) { should eq email }
  • 20. TEST SPY A more capableTest Stub allowing verification of indirect output from the SUT let(:spy_queue) { double(push: true) } let(:email) { “tom@crui.se” } before do Application.config.email_queue = spy_queue end subject { User.create(email: email) } it { should be_persisted } its(:username) { should eq email } it “should enqueue welcome message” do expect(spy_queue).to have_received(:push).with(email, “Ohai”) end
  • 21. DESIGNING FOR DOUBLES • Dependency Lookup • Dependency Injection
  • 22. class Buddy def good_friend?; on_tap.craft?; end def on_tap Fridge.cold_one end end describe Buddy, “serving coors” do # TODO control indirect input to the SUT it “should not be a good friend” do expect(subject).not_to be_good_friend end
  • 23. DEPENDENCY LOOKUP class Buddy def good_friend?; on_tap.craft?; end def on_tap Fridge.cold_one end end describe Buddy, “serving coors” do let(:coors) { double(craft?: false) } before { Fridge.stubs(:cold_one) { coors } } it “should not be a good friend” do expect(subject).not_to be_good_friend end
  • 24. class Buddy attr_accessor :fridge def good_friend?; on_tap.craft?; end def on_tap @fridge.cold_one end end describe Buddy, “serving coors” do let(:coors) { double(craft?: false) } let(:stub_fridge) { double(cold_one: coors) } before { subject.fridge = stub_fridge } it “should not be a good friend” do expect(subject).not_to be_good_friend end DEPENDENCY INJECTION
  • 26. class Buddy attr_reader :supermarket def make_breakfast(request=“Steak & eggs”) ingredients = supermarket.find(request) prepare(ingredients) end end
  • 27. TEST-SPECIFIC SUBCLASSES class Buddy attr_reader :supermarket def make_breakfast(request=“Steak & eggs”) ingredients = supermarket.find(request) prepare(ingredients) end end class TestBuddy < Buddy attr_writer :supermarket end
  • 28. TEST HOOKS class Buddy if ENV != “TEST” attr_reader :supermarket else attr_accessor :supermarket end def make_breakfast(request=“Steak & eggs”) ingredients = supermarket.find(request) prepare(ingredients) end end
  • 30. “MOCKIST”TDD / BDD • Uses mocks for all DOCs • Likes the test writing process to inform design decisions • Tests in strict isolation
  • 31. CLASSICTDD • Uses test doubles only for awkward DOCs, favoring “real” objects • Minimizes coupling between tests and implementation • Tests small clusters of components, not isolated units
  • 32. CLASSICTDDERS CONSIDER USING ATEST DOUBLE IF: • The behavior of the DOC cannot be changed/observed • Use of the DOC could cause unwanted side-effects • The DOC is too slow • The DOC doesn’t exist yet
  • 33. OVERUSE CAN LEADTO: • Over specified tests of the SUT’s process, not its result • Fragile tests that break when implementation changes • Untested integration • Less time on Hacker News while your build runs
  • 34. MORE xUnit Test Patterns: xunitpatterns.com Mocks aren’t Stubs by Martin Fowler: martinfowler.com/articles/mocksArentStubs.html A case against a case against mocking and stubbing by David Chelimsky: blog.davidchelimsky.net/2008/12/11/a-case-against-a-case-against-mocking-and-stubbing/ Timecop for testing time-dependent code: github.com/travisjeffery/timecop RSpec: rspec.info MiniTest: ruby-doc.org/stdlib Mocha: github.com/freerange/mocha