SlideShare a Scribd company logo
1 of 115
Download to read offline
Mocks Enabling
Test-Driven Design
Alexandre Martins
http://m.artins.net
Twitter: @amartinsn
Mocking Hell
http://blog.m.artins.net/tdd-listen-to-the-tests-
they-tell-smells-in-your-code/
Listen ToYour Tests,
They TellYou Smells
InYour Code
Duplicated
Implementation
describe ShowController, “index” do
context “when a TV show has no public videos” do
it “should not display any shows” do
Show.should_receive(:all)
.with(:select => “id,name,video_count”,
:conditions => “shows.video_count > 0”)
.and_return([])
get ‘index’
response.body.should_not(match(/
#{show.name}))
end
end
end
class ShowController
def index
@shows = Show.all(
:select => “id, name, video_count”,
:conditions => “shows.video_count > 0”
)
end
end
describe ShowController, “index” do
context “when a TV show has no public videos” do
it “should not display any shows” do
Show.should_receive(:all)
.with(:select => “id,name,video_count”,
:conditions => “shows.video_count > 0”)
.and_return([])
get ‘index’
response.body.should_not(match(/
#{show.name}))
end
end
end
class ShowController
def index
@shows = Show.all(
:select => “id, name, video_count”,
:conditions => “shows.video_count > 0”
)
end
end
Leads To Brittle
Tests That Do
A Poor Job
module Codebreaker
describe Game do
describe “#start” do
it “sends a welcome message” do
output = double(‘output’)
game = Game.new(output)
output.should_receive(:puts)
.with(‘Welcome to Codebreaker!’)
game.start
end
end
end
end
module Codebreaker
class Game
def initialize(output)
@output = output
end
def start
@output.puts(“Welcome to
Codebreaker!”)
end
end
end
Refactor To The
Following:
module Codebreaker
class Game
def initialize(output)
@output = output
end
def start
@output.write(“Welcome to
Codebreaker!”)
end
end
end
The Tests Fail!
The Output Does
Not Change
Mocks Suck?
Maybe
Or Maybe We Just
Don’t Understand
Them
Why Mocks?
MockObjects
+
Procedural
Programming
=
Bad Idea!
Mocks Are
Not Stubs!
Mocks
Assert On
Messages
Stubs Return
Values
describe ShowController, “index” do
context “when a TV show has no public videos” do
it “should not display any shows” do
Show.should_receive(:all)
.with(:select => “id,name,video_count”,
:conditions => “shows.video_count > 0”)
.and_return([])
get ‘index’
response.body.should_not(match(/
#{show.name}))
end
end
end
Asserting on State!
MockObjects
+
OOP
=
Good Idea!
Key Idea on
OOP:
Objects Tell
Objects To
Do Things
“The key in making great and growable
systems is much more to design how
its modules communicate rather than
what their internal behaviors should
be.”
-Alan Kay
Inventor of Smalltalk
Change The
Behavior Of
The System By
Composing
Objects
Example:
Ticket Machine
Interface
Ticket Reserve
System
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
ImagineYou Want
To Audit The
Requests Before
Processing Them...
Procedural
Programming
Way:Add Code
To The Method
For OO
Programming This
Violates The Single
Responsibility
Principle
Object-Oriented
Programming Way:
Change Object
Composition
Ticket Machine
Interface
Ticket Request
Auditing
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Ticket Reserve
System
Reserve
Tickets
What Would
The Code For
The Interface
Look Like?
class TicketMachineInterface
def initialize(request_handler)
@request_handler = request_handler
@current_display = “”
end
def number_pressed(number)
@current_display += number.to_s
end
def delete_pressed
@current_display.chop!
end
def submit_request
@request_handler.reserve(@current_display.to_i)
end
end
Notice Two
Things:
1. Follows Tell,
Don’t Ask
Principle
class TicketMachineInterface
def initialize(request_handler)
@request_handler = request_handler
@current_display = “”
end
def number_pressed(number)
@current_display += number.to_s
end
def delete_pressed
@current_display.chop!
end
def submit_request
@request_handler.reserve(@current_display.to_i)
end
end
2. Hides Its
Internal State
class TicketMachineInterface
def initialize(request_handler)
@request_handler = request_handler
@current_display = “”
end
def number_pressed(number)
@current_display += number.to_s
end
def delete_pressed
@current_display.chop!
end
def submit_request
@request_handler.reserve(@current_display.to_i)
end
end
How Can We
Assert On
State?
You Would
Have To Add
Getters Just
For Tests?
Bad Idea!
How ThenYou
Do Tests?
Ticket Machine
Interface
Ticket Reserve
System
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Ticket Machine
Interface
Ticket Reserve
System
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Assert On The Message
How?
Ticket Machine
Interface
Fake Object
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Ticket Machine
Interface
Mock Object
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
describe TicketMachineInterface do
it “reserves the number of tickets inputted when
user submits the request” do
request_handler = double(‘request_handler’)
request_handler.should_receive(:reserve).with(55)
machine =
TicketMachineInterface.new(request_handler)
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
describe TicketMachineInterface do
it “reserves the number of tickets inputted when
user submits the request” do
request_handler = double(‘request_handler’)
request_handler.should_receive(:reserve).with(55)
machine =
TicketMachineInterface.new(request_handler)
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
describe TicketMachineInterface do
it “reserves the number of tickets inputted when
user submits the request” do
request_handler = double(‘request_handler’)
request_handler.should_receive(:reserve).with(55)
machine =
TicketMachineInterface.new(request_handler)
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
Ticket Machine
Interface
Mock Object
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
describe TicketMachineInterface do
it “reserves the number of tickets inputted when
user submits the request” do
request_handler = double(‘request_handler’)
request_handler.should_receive(:reserve).with(55)
machine =
TicketMachineInterface.new(request_handler)
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
Key Idea
In OOP,
Behavior Is
Found In The
Messages
Mocks Assert
On The
Messages Going
Between The
Objects
Key
Mocking
Rules...
1. Mock Roles,
Not Objects
http://www.jmock.org/oopsla2004.pdf
Wanting To Mock
Concrete Objects
Is A Design Smell
Well Design
Object Don’t
Know Explicitly
Who They Are
Talking To
Why?
Because Who
They’re Talking To
Can Change
They Should Only
Know The ROLE
Their Collaborator
Is Playing
Ticket Machine
Interface
Ticket Reserve
System
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Ticket Machine
Request Handler
(ROLE)
Ticket Machine
Interface
Ticket Request
Auditing
Reserve Tickets
Number Pressed
Delete Pressed
Submit Request
Ticket Reserve
System
Reserve
Tickets
Ticket Machine
Request Handler
(ROLE)
When Mocking
Roles,TDD
Becomes A
Design Process
class TicketMachineInterface
def number_pressed(number)
end
def delete_pressed
end
def submit_request
end
end
describe TicketMachineInterface do
it “reserves the correct number of tickets when a
number is pressed two times before submitting” do
machine =
TicketMachineInterface.new
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
describe TicketMachineInterface do
it “reserves the number of tickets inputted when
user submits the request” do
request_handler = double(‘request_handler’)
request_handler.should_receive(:reserve).with(55)
machine =
TicketMachineInterface.new(request_handler)
machine.number_pressed(5)
machine.number_pressed(5)
machine.submit_request
end
end
Not the actual object
being implemented, but
the role that object is
going to play
class TicketMachineInterface
def initialize(request_handler)
@request_handler = request_handler
end
def number_pressed(number)
end
def delete_pressed
end
def submit_request
@request_handler.reserve(@current_display)
end
end
class TicketMachineInterface
def initialize(request_handler)
@request_handler = request_handler
@current_display = “”
end
def number_pressed(number)
@current_display += number.to_s
end
def delete_pressed
end
def submit_request
@request_handler.reserve(@current_display.to_i)
end
end
2. Only Mock
Types That
You Own
IfYou Don’t
Own The API,
There’s No
Design Feedback
Instead Of
Mocking A Role,
You’re
Mocking An
Implementation
DuplicatingYour
Production Code
InYour Test Is A
Test Smell
This Means
Don’t Mock
Boundary
Objects
module Codebreaker
describe Game do
describe “#start” do
it “sends a welcome message” do
output = double(‘output’)
game = Game.new(output)
output.should_receive(:puts)
.with(‘Welcome to Codebreaker!’)
game.start
end
end
end
end
module Codebreaker
class Game
def initialize(output)
@output = output
end
def start
@output.puts(“Welcome to
Codebreaker!”)
end
end
end
We’re coupling it to
the actual Ruby
standard output
The responsibility of this
game is to talk to a
command-line interface
What Should
We Do?
Mock The Role
In The Domain
Object
module Codebreaker
describe Game do
describe “#start” do
it “sends a welcome message” do
displayer = double(‘displayer’)
game = Game.new(displayer)
displayer.should_receive(:display)
.with(‘Welcome to Codebreaker!’)
game.start
end
end
end
end
module Codebreaker
class Game
def initialize(displayer)
@displayer = displayer
end
def start
@displayer.display(“Welcome
to Codebreaker!”)
end
end
end
Implement The
Displayer Role
Using Puts
How Is This Any
Better?
Now The
Responsibility of The
Game Is To Welcome
New Players Through
A Displayer
Now I Can Move From
Displaying The Message
On A Command-Line
Interface To A
RichGUI...
...Without Having To
Change Codebreaker
Object!
Open/Closed Principle
“Where Objects
Should Be Open For
Extension, But Closed
For Modification”
-Bob Martin
What About
Testing The
Display Object?
Integration Tests
/ Acceptance
Tests
3. Only Mock
Peers Not
Internals
Decide What
Behavior Is Inside
And What’s
OutsideYour
Object
Does this implementation belong internal to my
object, or as a collaborator to my object?
Single Responsibility
Principle
“A Class Should Have
Only One Reason To
Change”
-Bob Martin
Is This My Role?
Auction Server
Auction Message
Translator
Process
Message
Different Types
Of Messages
Come In
Translator
Translates Them
Into Domain
describe AuctionMessageTranslator
it “notifies bid details when current price message
received” do
listener = double(‘event_listener’)
listener.should_receive(:current_price)
.with(192, 7)
translator = AuctionMessageTranslator.new(listener)
message = Message.new(“SOLVersion: 1.1;
Event: Price; CurrentPrice: 192; Increment: 7;
Bidder: Someone Else”)
translator.process_message(message)
end
end
class AuctionMessageTranslator
def initialize(listener)
@listener = listener
end
def process_message(message)
event = unpack_event_from(message)
if event.type == “CLOSE”
@listener.auction_closed
else
@listener.current_price(event.current_price,
event.increment)
end
end
private
def unpack_event_from(message)
AuctionMessageEvent.new(message)
end
end
class AuctionMessageTranslator
def initialize(listener)
@listener = listener
end
def process_message(message)
event = unpack_event_from(message)
if event.type == “CLOSE”
@listener.auction_closed
else
@listener.current_price(event.current_price,
event.increment)
end
end
private
def unpack_event_from(message)
AuctionMessageEvent.new(message)
end
end
class AuctionMessageTranslator
def initialize(listener)
@listener = listener
end
def process_message(message)
event = unpack_event_from(message)
if event.type == “CLOSE”
@listener.auction_closed
else
@listener.current_price(event.current_price,
event.increment)
end
end
private
def unpack_event_from(message)
AuctionMessageEvent.new(message)
end
end
Internal
Object
Don’t Mock It!
Don’t Stub It!
Why?
It’s An
Implementation
Detail
Wanna Learn
More?
Read:
Thanks!

More Related Content

What's hot

The Ring programming language version 1.10 book - Part 97 of 212
The Ring programming language version 1.10 book - Part 97 of 212The Ring programming language version 1.10 book - Part 97 of 212
The Ring programming language version 1.10 book - Part 97 of 212Mahmoud Samir Fayed
 
Quill vs Slick Smackdown
Quill vs Slick SmackdownQuill vs Slick Smackdown
Quill vs Slick SmackdownAlexander Ioffe
 
Introduction to Quill - Postgres Conf Philly 2019
Introduction to Quill - Postgres Conf Philly 2019Introduction to Quill - Postgres Conf Philly 2019
Introduction to Quill - Postgres Conf Philly 2019Alexander Ioffe
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Coupa Software
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsHéla Ben Khalfallah
 
Sql Commands
Sql CommandsSql Commands
Sql CommandsSachin MK
 
Dynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsDynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsBroadleaf Commerce
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)tompunk
 
Web Developer make the most out of your Database !
Web Developer make the most out of your Database !Web Developer make the most out of your Database !
Web Developer make the most out of your Database !Jean-Marc Desvaux
 
EAV in Magento
EAV in MagentoEAV in Magento
EAV in Magentohazzaz
 
e computer notes - Manipulating data
e computer notes - Manipulating datae computer notes - Manipulating data
e computer notes - Manipulating dataecomputernotes
 
Rest in practice con Symfony2
Rest in practice con Symfony2Rest in practice con Symfony2
Rest in practice con Symfony2Daniel Londero
 

What's hot (20)

Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
The Ring programming language version 1.10 book - Part 97 of 212
The Ring programming language version 1.10 book - Part 97 of 212The Ring programming language version 1.10 book - Part 97 of 212
The Ring programming language version 1.10 book - Part 97 of 212
 
Quill vs Slick Smackdown
Quill vs Slick SmackdownQuill vs Slick Smackdown
Quill vs Slick Smackdown
 
Les15
Les15Les15
Les15
 
Introduction to Quill - Postgres Conf Philly 2019
Introduction to Quill - Postgres Conf Philly 2019Introduction to Quill - Postgres Conf Philly 2019
Introduction to Quill - Postgres Conf Philly 2019
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental Concepts
 
Zend framework 04 - forms
Zend framework 04 - formsZend framework 04 - forms
Zend framework 04 - forms
 
Sql Commands
Sql CommandsSql Commands
Sql Commands
 
Les06
Les06Les06
Les06
 
Dynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsDynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java Annotations
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
 
Practical Object Oriented Models In Sql
Practical Object Oriented Models In SqlPractical Object Oriented Models In Sql
Practical Object Oriented Models In Sql
 
Web Developer make the most out of your Database !
Web Developer make the most out of your Database !Web Developer make the most out of your Database !
Web Developer make the most out of your Database !
 
Les07
Les07Les07
Les07
 
EAV in Magento
EAV in MagentoEAV in Magento
EAV in Magento
 
e computer notes - Manipulating data
e computer notes - Manipulating datae computer notes - Manipulating data
e computer notes - Manipulating data
 
Rest in practice con Symfony2
Rest in practice con Symfony2Rest in practice con Symfony2
Rest in practice con Symfony2
 
Tulip
TulipTulip
Tulip
 

Similar to Mocks Enabling Test-Driven Design

GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant TrainingAidIQ
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developersLuiz Messias
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and viewspriestc
 
please code in c#- please note that im a complete beginner- northwind.docx
please code in c#- please note that im a complete beginner-  northwind.docxplease code in c#- please note that im a complete beginner-  northwind.docx
please code in c#- please note that im a complete beginner- northwind.docxAustinaGRPaigey
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Plataformatec
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Ajax control tool kit
Ajax control tool kitAjax control tool kit
Ajax control tool kitVidhi Patel
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docx
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docxExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docx
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docxSusanaFurman449
 
Mp24: The Bachelor, a facebook game
Mp24: The Bachelor, a facebook gameMp24: The Bachelor, a facebook game
Mp24: The Bachelor, a facebook gameMontreal Python
 
Acceptance Testing With Selenium
Acceptance Testing With SeleniumAcceptance Testing With Selenium
Acceptance Testing With Seleniumelliando dias
 
Techno71-Gadget-Factory (Amit Chowdhury).pptx
Techno71-Gadget-Factory (Amit Chowdhury).pptxTechno71-Gadget-Factory (Amit Chowdhury).pptx
Techno71-Gadget-Factory (Amit Chowdhury).pptxAmitChowdhury57
 

Similar to Mocks Enabling Test-Driven Design (20)

GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and views
 
Java calculator
Java calculatorJava calculator
Java calculator
 
please code in c#- please note that im a complete beginner- northwind.docx
please code in c#- please note that im a complete beginner-  northwind.docxplease code in c#- please note that im a complete beginner-  northwind.docx
please code in c#- please note that im a complete beginner- northwind.docx
 
Cc code cards
Cc code cardsCc code cards
Cc code cards
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Chapter9 r studio2
Chapter9 r studio2Chapter9 r studio2
Chapter9 r studio2
 
Ajax control tool kit
Ajax control tool kitAjax control tool kit
Ajax control tool kit
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
Vue.js slots.pdf
Vue.js slots.pdfVue.js slots.pdf
Vue.js slots.pdf
 
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docx
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docxExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docx
ExplanationDesignerCodeGlobal.Microsoft.VisualBasic.Compiler.docx
 
Mp24: The Bachelor, a facebook game
Mp24: The Bachelor, a facebook gameMp24: The Bachelor, a facebook game
Mp24: The Bachelor, a facebook game
 
Acceptance Testing With Selenium
Acceptance Testing With SeleniumAcceptance Testing With Selenium
Acceptance Testing With Selenium
 
Techno71-Gadget-Factory (Amit Chowdhury).pptx
Techno71-Gadget-Factory (Amit Chowdhury).pptxTechno71-Gadget-Factory (Amit Chowdhury).pptx
Techno71-Gadget-Factory (Amit Chowdhury).pptx
 

Recently uploaded

why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 

Recently uploaded (20)

why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 

Mocks Enabling Test-Driven Design