SlideShare a Scribd company logo
1 of 84
Download to read offline
TDD As If You Meant It
Alex Bolboacă,  @alexboly,  alex.bolboaca@mozaicworks.com
October 2017
Test Driven Development
TDD As If You Meant It
A Simple Example
Practising TDD As If You Meant It
Applying TDD As If You Meant It in Production
Closing
Test Driven Development
Like Brewing Coffee
TDD is like brewing coffee
My Definition
A process for designing software incrementally by clarifying the problem
before the solution, and allowing the solution to appear from the tension
between tests and existing code.
Emergent design
The design is an emergent property because it appears from a combination
of properties of programmer, test code and production code.
So, …
When doing “pure” TDD, you shouldn’t start with any preconceived ideas
about the solution
But…
Most of the time we fail at this rule
Goal
The goal is not to ignore your past experience.
The goal is to allow yourself to gather more experiences.
TDD As If You Meant It
What Is It?
A set of constraints that force the practise of “pure” TDD.
Constraints
You are not allowed to create any:
• named constant
• variable
• method
• class
other than by refactoring it out of a test.
Constraints
All production code is first written in tests and then extracted through
refactoring
A Simple Example
We Need A Problem
Bank account kata
Think of your personal bank account experience. When in doubt, go for the
simplest solution.
Requirements
• Deposit and Withdrawal
• Transfer
• Account statement (date, amount, balance)
• Statement printing
• Statement filters (just deposits, withdrawal, date)
Source: https://github.com/sandromancuso/Bank-kata/
Technology
I’ll use groovy and spock
First test
def ”the first test”(){
expect:
false
}
Isn’t this beautiful?
Let’s take the time to properly admire the serenity and simplicity of this test ⌣
First weird question
What is false?
False in programming
In logic, false is a truth value associated to an assertion.
In programming false is either a constant or the result of a boolean
operation.
So what is false?
def ”after a deposit of €5 in an empty account 
its balance is €5”{
expect:
424532534 == 5
}
Make the first test pass
def ”after a deposit of €5 in an empty account 
its balance is €5”{
expect:
0 + 5 == 5
}
Celebrate!
Yay!
Refactor
Remember We’re only allowed to:
• extract constant
• extract variable
• remove duplication
The test needs more clarity
0 + 5 == 5
What is 5? What is 0?
• 0: initial account balance
• first 5: deposit amount
• second 5: final account balance
 Accidental duplication!
Clarity
def ”after a deposit of €5 in an empty account 
its balance is €5”{
given:
def expectedFinalBalance = 5
def initialBalance = 0
def amount = 5
when:
def finalBalance = initialBalance + amount
then:
finalBalance == expectedFinalBalance
}
Notions …
Let’s take a look at the notions we’re using:
• deposit amount
• empty account
• balance
• initial balance
• final balance
Semantics
Empty account = account that has an initial balance of 0
 Duplication!
Express it!
def ”after depositing €5 in an account with balance 0 
its balance is €5”{
given:
def expectedFinalBalance = 5
def initialBalance = 0
def amount = 5
when: // Production code
def finalBalance = initialBalance + amount
then:
finalBalance == expectedFinalBalance
}
Next test?
Triangulation: the process of writing another test that changes a single
input from the input set with the goal of advancing towards the solution
Triangulation - Advanced
We triangulate in the topology of possible solutions
What can we triangulate on?
• initial balance
• deposit amount
• currency (€, RON, £)
• account (eg. ownership, type of account etc.)
Decision
Let’s triangulate on deposit
What are interesting values for deposit?
Value sampling or Equivalence partitioning
Since we cannot test all the values, find the intervals that are interesting
and pick at least one value from each interval
Equivalence partitioning for deposit
• Negative numbers: e.g. -€1, -€5
• Zero
• Positive numbers
• Minimum ?
• Maximum ?
• Non-integers: e.g. €1.50, €99.99
Questions, questions…
Can an account have negative balance? Yes
Can we deposit a negative amount? No
What’s the maximum amount in an account? Use €1.000.000.000
What’s the minimum amount in an account? Use -€10.000
What’s the minimum deposit? Use €1
What’s the maximum deposit? Use €1.000.000.000
So, triangulation on deposit
Accepted values:
• Minimum: €1
• Any value between €1 and €1.000.000.000
• Maximum: €1.000.000.000 (in an account with 0)
Invalid values:
• Less than minimum: €0.99
• More than maximum: €1.000.000.000,01
Second test
def ”after a deposit of €1 in an account with balance 0 
its balance is €1”{
expect:
false
}
What is false?
def ”after a deposit of €1 in an account with balance 0
its balance is €1”{
expect:
1 == 0 + 241234123423
}
Make it pass
def ”after a deposit of €1 in an account with balance 0
its balance is €1”{
expect:
1 == 0 + 1
}
Refactor to clarify
def ”after a deposit of €1 in an account with balance 0
its balance is €1”{
given:
def initialBalance = 0
def amount = 1
def expectedFinalBalance = 1
when: //Production code
def finalBalance = initialBalance + amount
then:
expectedFinalBalance == finalBalance
}
More refactoring?
Duplication between tests!
Rule of three
Rule of Three
 Remove duplication after you’ve seen it for 3 or more times
So, next test
def ”after a deposit of €1.000.000.000 in an account
with balance 0 its balance is €1.000.000.000”{
expect:
false
}
5 minutes later …
def ”after a deposit of €1.000.000.000 in an account
with balance 0 its balance is €1.000.000.000”{
given:
def initialBalance = 0
def amount = 1000000000
def expectedFinalBalance = 1000000000
when: //Production code
def finalBalance = initialBalance + amount
then:
expectedFinalBalance == finalBalance
}
Anything else to refactor?
Q: What is 1.000.000.000?
A: Maximum balance for an account in € is €1.000.000.000.
Extract max balance
static final maxBalance = 1000000000
def ”after a deposit of #maxBalance in an account
with balance 0 its balance is #maxBalance”{
given:
def initialBalance = 0
def amount = maxBalance
def expectedFinalBalance = maxBalance
when: //Production code
def finalBalance = initialBalance + amount
then:
expectedFinalBalance == finalBalance
}
How to Remove Duplication?
Two options:
• remove duplication from tests using data driven tests
• remove duplication from production code using a method
Data driven tests?
def ”after a deposit of #amount in an account
with balance #balance
its balance is #expectedFinalBalance”{
when: ”deposit”
def finalBalance = initialBalance + amount
then:
expectedFinalBalance == finalBalance
where:
initialBalance | amount || expectedFinalBalance
0 | 1 || 1
0 | 5 || 5
0 | maxBalance || maxBalance
Hmm…
 Feels like it doesn’t advance the solution
Spoiler: I’ll come back to this later
Extract production code
def deposit(initialBalance, amount){
return initialBalance + amount
}
Reflection time
How’s it going?
Let’s reflect
• We didn’t write a lot of code: three tests and one line of production
code
• We learned a lot about the domain
• We learned a lot about the business rules
• We named things
• We have the simplest solution to the problem so far
• It feels slow
Most importantly
We can see how the code evolves: constant -> variable -> method
Let’s Look Into The Future: Deposit
static final maxBalance = 1000000000
def deposit(amount, initialBalance){
if(amount < 1)
return initialBalance
if(initialBalance + amount > maxBalance)
return initialBalance
return initialBalance + amount
}
Let’s Look Into The Future: Withdrawal
static final minBalance = -50000
def withdraw(amount, initialBalance){
if(amount < 1)
return initialBalance
if(initialBalance - amount < minBalance)
return initialBalance
return initialBalance - amount
}
We have a design choice
Go functional or go Object Oriented
Functional solution
def balance = deposit(10,
withdraw(200,
withdraw(500,
withdraw(10,
deposit(1000, /*initialBalance*/ 0)))))
Object Oriented Solution
def account = new Account(balance: 0)
account.deposit(1000)
account.withdraw(10)
account.withdraw(500)
account.withdraw(200)
account.deposit(10)
def balance = account.balance
Different Object Oriented Solution
def account = new Account(balance: 0)
def transactions = [
new DepositTransaction(amount: 1000),
new WithdrawalTransaction(amount: 10),
new WithdrawalTransaction(amount: 500),
new WithdrawalTransaction(amount: 200),
new DepositTransaction(amount: 10)
]
account.applyTransactions(transactions)
def balance = account.balance
What’s the difference?
A class is nothing more than a set of cohesive, partially applied pure
functions
– via JB Rainsberger
Partially applied function
account.deposit(amount)
is a partial application of:
deposit(amount, initialBalance)
And now for something completely different…
Pssst… Huge Monty Python fan here
Let’s rewind …
def ”after a deposit of #deposit in an account
with balance 0
its balance is #deposit”{
when: ”deposit”
def finalBalance = initialBalance + amount
then:
expectedFinalBalance == finalBalance
where:
initialBalance | amount || expectedFinalBalance
0 | 1 || 1
0 | 5 || 5
0 | maxBalance || maxBalance
And reinterpret this
Whenever we deposit a deposit amount less or equal to the maximum
balance into an account that has initial balance 0, the resulting balance is
the deposit amount
 Property based testing
Spock Genesis
spock-genesis library
https://github.com/Bijnagte/spock-genesis
A library that helps generating values for properties
A property based test
def ”after a deposit in an account
with balance 0
its balance is the deposit amount”{
when: ”deposit”
def finalBalance = deposit(amount,
initialBalance)
then:
expectedFinalBalance == finalBalance
where:
amount << integer(1..maxBalance).take(500)
initialBalance = 0
expectedFinalBalance = amount
Reflection time
• We’ve learned more about software design
• We’ve learned more about testing
• We left our options open until we picked functional or OO approach
• We decided step by step what’s the right next step
• Still feels slow
Practising TDD As If You Meant It
How
• Pick any kata, or a pet project
• Set up a timer at 45’
• Do it every day for 10 days (continue where you left off)
• Reflect on the way the design evolves, and on the design options you
took
•  Make every decision as deliberate as possible
Applying TDD As If You Meant It in
Production
Do It Like Mythbusters
Mythbusters
How?
• Separate a small(ish) problem. Eg: special alerts in a web application,
validation in client-side code, a UI control etc.
How?
• Separate a small(ish) problem. Eg: special alerts in a web application,
validation in client-side code, a UI control etc.
• Start a new test suite (maybe even a new project)
How?
• Separate a small(ish) problem. Eg: special alerts in a web application,
validation in client-side code, a UI control etc.
• Start a new test suite (maybe even a new project)
• Write the implementation using TDD as If You Meant It
How?
• Separate a small(ish) problem. Eg: special alerts in a web application,
validation in client-side code, a UI control etc.
• Start a new test suite (maybe even a new project)
• Write the implementation using TDD as If You Meant It
• When you have the production code, integrate it with the rest of the
code
Closing
Conclusions
TDD As If You Meant It has helped me become more deliberate about
software design.
• Despite feeling slow, I found it is quite fast after practising
Conclusions
TDD As If You Meant It has helped me become more deliberate about
software design.
• Despite feeling slow, I found it is quite fast after practising
• It helped me understand more about functional programming
Conclusions
TDD As If You Meant It has helped me become more deliberate about
software design.
• Despite feeling slow, I found it is quite fast after practising
• It helped me understand more about functional programming
• The feeling of working on a small, clean, piece of code instead of the
“big” code is very liberating
My advice
Embrace constraints
“I have never been forced to accept compromises but I
have willingly accepted constraints”
Charles Eames, Designer and Architect
Learn more
Adi’s Blog http://blog.adrianbolboaca.ro
Thank you!
I’ve been Alex Bolboacă, @alexboly, alex.bolboaca@mozaicworks.com
programmer, trainer, mentor, writer
at Mozaic Works
Think. Design. Work Smart.
https://mozaicworks.com
Q&A
Q&A

More Related Content

Similar to TDD As If You Meant It

Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...
Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...
Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...Andrés Viedma Peláez
 
Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDeclan Whelan
 
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docx
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docxCSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docx
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docxruthannemcmullen
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test communityKerry Buckley
 
The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189Mahmoud Samir Fayed
 
Break Even Analysis
Break Even AnalysisBreak Even Analysis
Break Even AnalysisARIES TIBAR
 
Introduction to Python - Training for Kids
Introduction to Python - Training for KidsIntroduction to Python - Training for Kids
Introduction to Python - Training for KidsAimee Maree Forsstrom
 
Test Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksTest Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksRubén Bernárdez
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in PythonSubhash Bhushan
 

Similar to TDD As If You Meant It (20)

TDD, BDD and mocks
TDD, BDD and mocksTDD, BDD and mocks
TDD, BDD and mocks
 
Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...
Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...
Por qué usar Spock en lugar de JUnit / Mockito para tus tests Java - Codemoti...
 
Decimals part 02
Decimals   part 02 Decimals   part 02
Decimals part 02
 
Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with Rails
 
Module 7
Module 7Module 7
Module 7
 
Testing in Django
Testing in DjangoTesting in Django
Testing in Django
 
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docx
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docxCSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docx
CSC139 Chapter 9 Lab Assignments (1) Classes and Obj.docx
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189The Ring programming language version 1.6 book - Part 41 of 189
The Ring programming language version 1.6 book - Part 41 of 189
 
Break Even Analysis
Break Even AnalysisBreak Even Analysis
Break Even Analysis
 
Introduction to Python - Training for Kids
Introduction to Python - Training for KidsIntroduction to Python - Training for Kids
Introduction to Python - Training for Kids
 
Flowchart
FlowchartFlowchart
Flowchart
 
fm10e ch 10.pptx
fm10e ch 10.pptxfm10e ch 10.pptx
fm10e ch 10.pptx
 
T4
T4T4
T4
 
Introduction to c part -1
Introduction to c   part -1Introduction to c   part -1
Introduction to c part -1
 
Vb scripting
Vb scriptingVb scripting
Vb scripting
 
Test Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocksTest Doubles - stubs, spies & mocks
Test Doubles - stubs, spies & mocks
 
Calculator Processing
Calculator ProcessingCalculator Processing
Calculator Processing
 
Vba class 4
Vba class 4Vba class 4
Vba class 4
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in Python
 

More from Alexandru Bolboaca (20)

Refactor legacy code through pure functions
Refactor legacy code through pure functionsRefactor legacy code through pure functions
Refactor legacy code through pure functions
 
Design Without Types
Design Without TypesDesign Without Types
Design Without Types
 
Thinking in Functions
Thinking in FunctionsThinking in Functions
Thinking in Functions
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
 
The Journey to Master Code Design
The Journey to Master Code DesignThe Journey to Master Code Design
The Journey to Master Code Design
 
What is good software design? And why it matters?
What is good software design? And why it matters?What is good software design? And why it matters?
What is good software design? And why it matters?
 
Functional programming in C++
Functional programming in C++Functional programming in C++
Functional programming in C++
 
Agile Technical Leadership
Agile Technical LeadershipAgile Technical Leadership
Agile Technical Leadership
 
Usable Software Design
Usable Software DesignUsable Software Design
Usable Software Design
 
Hidden loops
Hidden loopsHidden loops
Hidden loops
 
Removing structural duplication
Removing structural duplicationRemoving structural duplication
Removing structural duplication
 
Continuous delivery
Continuous deliveryContinuous delivery
Continuous delivery
 
Why You Should Start Using Docker
Why You Should Start Using DockerWhy You Should Start Using Docker
Why You Should Start Using Docker
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
 
Applied craftsmanship
Applied craftsmanshipApplied craftsmanship
Applied craftsmanship
 
Pyramid of-developer-skills
Pyramid of-developer-skillsPyramid of-developer-skills
Pyramid of-developer-skills
 
Stay focused
Stay focusedStay focused
Stay focused
 
Kanban intro
Kanban introKanban intro
Kanban intro
 
Unit testing-patterns
Unit testing-patternsUnit testing-patterns
Unit testing-patterns
 
Incremental design, simply explained
Incremental design, simply explainedIncremental design, simply explained
Incremental design, simply explained
 

Recently uploaded

Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
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
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
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
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
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
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
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
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
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
 

Recently uploaded (20)

Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
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
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
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
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
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
 
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
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
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)
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
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
 

TDD As If You Meant It

  • 1. TDD As If You Meant It Alex Bolboacă,  @alexboly,  alex.bolboaca@mozaicworks.com October 2017
  • 2. Test Driven Development TDD As If You Meant It A Simple Example Practising TDD As If You Meant It Applying TDD As If You Meant It in Production Closing
  • 4. Like Brewing Coffee TDD is like brewing coffee
  • 5. My Definition A process for designing software incrementally by clarifying the problem before the solution, and allowing the solution to appear from the tension between tests and existing code.
  • 6. Emergent design The design is an emergent property because it appears from a combination of properties of programmer, test code and production code.
  • 7. So, … When doing “pure” TDD, you shouldn’t start with any preconceived ideas about the solution
  • 8. But… Most of the time we fail at this rule
  • 9. Goal The goal is not to ignore your past experience. The goal is to allow yourself to gather more experiences.
  • 10. TDD As If You Meant It
  • 11. What Is It? A set of constraints that force the practise of “pure” TDD.
  • 12. Constraints You are not allowed to create any: • named constant • variable • method • class other than by refactoring it out of a test.
  • 13. Constraints All production code is first written in tests and then extracted through refactoring
  • 15. We Need A Problem Bank account kata Think of your personal bank account experience. When in doubt, go for the simplest solution. Requirements • Deposit and Withdrawal • Transfer • Account statement (date, amount, balance) • Statement printing • Statement filters (just deposits, withdrawal, date) Source: https://github.com/sandromancuso/Bank-kata/
  • 17. First test def ”the first test”(){ expect: false }
  • 18. Isn’t this beautiful? Let’s take the time to properly admire the serenity and simplicity of this test ⌣
  • 20. False in programming In logic, false is a truth value associated to an assertion. In programming false is either a constant or the result of a boolean operation.
  • 21. So what is false? def ”after a deposit of €5 in an empty account its balance is €5”{ expect: 424532534 == 5 }
  • 22. Make the first test pass def ”after a deposit of €5 in an empty account its balance is €5”{ expect: 0 + 5 == 5 }
  • 24. Refactor Remember We’re only allowed to: • extract constant • extract variable • remove duplication
  • 25. The test needs more clarity 0 + 5 == 5 What is 5? What is 0? • 0: initial account balance • first 5: deposit amount • second 5: final account balance  Accidental duplication!
  • 26. Clarity def ”after a deposit of €5 in an empty account its balance is €5”{ given: def expectedFinalBalance = 5 def initialBalance = 0 def amount = 5 when: def finalBalance = initialBalance + amount then: finalBalance == expectedFinalBalance }
  • 27. Notions … Let’s take a look at the notions we’re using: • deposit amount • empty account • balance • initial balance • final balance
  • 28. Semantics Empty account = account that has an initial balance of 0  Duplication!
  • 29. Express it! def ”after depositing €5 in an account with balance 0 its balance is €5”{ given: def expectedFinalBalance = 5 def initialBalance = 0 def amount = 5 when: // Production code def finalBalance = initialBalance + amount then: finalBalance == expectedFinalBalance }
  • 30. Next test? Triangulation: the process of writing another test that changes a single input from the input set with the goal of advancing towards the solution
  • 31. Triangulation - Advanced We triangulate in the topology of possible solutions
  • 32. What can we triangulate on? • initial balance • deposit amount • currency (€, RON, £) • account (eg. ownership, type of account etc.)
  • 34. What are interesting values for deposit? Value sampling or Equivalence partitioning Since we cannot test all the values, find the intervals that are interesting and pick at least one value from each interval
  • 35. Equivalence partitioning for deposit • Negative numbers: e.g. -€1, -€5 • Zero • Positive numbers • Minimum ? • Maximum ? • Non-integers: e.g. €1.50, €99.99
  • 36. Questions, questions… Can an account have negative balance? Yes Can we deposit a negative amount? No What’s the maximum amount in an account? Use €1.000.000.000 What’s the minimum amount in an account? Use -€10.000 What’s the minimum deposit? Use €1 What’s the maximum deposit? Use €1.000.000.000
  • 37. So, triangulation on deposit Accepted values: • Minimum: €1 • Any value between €1 and €1.000.000.000 • Maximum: €1.000.000.000 (in an account with 0) Invalid values: • Less than minimum: €0.99 • More than maximum: €1.000.000.000,01
  • 38. Second test def ”after a deposit of €1 in an account with balance 0 its balance is €1”{ expect: false }
  • 39. What is false? def ”after a deposit of €1 in an account with balance 0 its balance is €1”{ expect: 1 == 0 + 241234123423 }
  • 40. Make it pass def ”after a deposit of €1 in an account with balance 0 its balance is €1”{ expect: 1 == 0 + 1 }
  • 41. Refactor to clarify def ”after a deposit of €1 in an account with balance 0 its balance is €1”{ given: def initialBalance = 0 def amount = 1 def expectedFinalBalance = 1 when: //Production code def finalBalance = initialBalance + amount then: expectedFinalBalance == finalBalance }
  • 43. Rule of three Rule of Three  Remove duplication after you’ve seen it for 3 or more times
  • 44. So, next test def ”after a deposit of €1.000.000.000 in an account with balance 0 its balance is €1.000.000.000”{ expect: false }
  • 45. 5 minutes later … def ”after a deposit of €1.000.000.000 in an account with balance 0 its balance is €1.000.000.000”{ given: def initialBalance = 0 def amount = 1000000000 def expectedFinalBalance = 1000000000 when: //Production code def finalBalance = initialBalance + amount then: expectedFinalBalance == finalBalance }
  • 46. Anything else to refactor? Q: What is 1.000.000.000? A: Maximum balance for an account in € is €1.000.000.000.
  • 47. Extract max balance static final maxBalance = 1000000000 def ”after a deposit of #maxBalance in an account with balance 0 its balance is #maxBalance”{ given: def initialBalance = 0 def amount = maxBalance def expectedFinalBalance = maxBalance when: //Production code def finalBalance = initialBalance + amount then: expectedFinalBalance == finalBalance }
  • 48. How to Remove Duplication? Two options: • remove duplication from tests using data driven tests • remove duplication from production code using a method
  • 49. Data driven tests? def ”after a deposit of #amount in an account with balance #balance its balance is #expectedFinalBalance”{ when: ”deposit” def finalBalance = initialBalance + amount then: expectedFinalBalance == finalBalance where: initialBalance | amount || expectedFinalBalance 0 | 1 || 1 0 | 5 || 5 0 | maxBalance || maxBalance
  • 50. Hmm…  Feels like it doesn’t advance the solution Spoiler: I’ll come back to this later
  • 51. Extract production code def deposit(initialBalance, amount){ return initialBalance + amount }
  • 53. Let’s reflect • We didn’t write a lot of code: three tests and one line of production code • We learned a lot about the domain • We learned a lot about the business rules • We named things • We have the simplest solution to the problem so far • It feels slow
  • 54. Most importantly We can see how the code evolves: constant -> variable -> method
  • 55. Let’s Look Into The Future: Deposit static final maxBalance = 1000000000 def deposit(amount, initialBalance){ if(amount < 1) return initialBalance if(initialBalance + amount > maxBalance) return initialBalance return initialBalance + amount }
  • 56. Let’s Look Into The Future: Withdrawal static final minBalance = -50000 def withdraw(amount, initialBalance){ if(amount < 1) return initialBalance if(initialBalance - amount < minBalance) return initialBalance return initialBalance - amount }
  • 57. We have a design choice Go functional or go Object Oriented
  • 58. Functional solution def balance = deposit(10, withdraw(200, withdraw(500, withdraw(10, deposit(1000, /*initialBalance*/ 0)))))
  • 59. Object Oriented Solution def account = new Account(balance: 0) account.deposit(1000) account.withdraw(10) account.withdraw(500) account.withdraw(200) account.deposit(10) def balance = account.balance
  • 60. Different Object Oriented Solution def account = new Account(balance: 0) def transactions = [ new DepositTransaction(amount: 1000), new WithdrawalTransaction(amount: 10), new WithdrawalTransaction(amount: 500), new WithdrawalTransaction(amount: 200), new DepositTransaction(amount: 10) ] account.applyTransactions(transactions) def balance = account.balance
  • 61. What’s the difference? A class is nothing more than a set of cohesive, partially applied pure functions – via JB Rainsberger
  • 62. Partially applied function account.deposit(amount) is a partial application of: deposit(amount, initialBalance)
  • 63. And now for something completely different… Pssst… Huge Monty Python fan here
  • 64. Let’s rewind … def ”after a deposit of #deposit in an account with balance 0 its balance is #deposit”{ when: ”deposit” def finalBalance = initialBalance + amount then: expectedFinalBalance == finalBalance where: initialBalance | amount || expectedFinalBalance 0 | 1 || 1 0 | 5 || 5 0 | maxBalance || maxBalance
  • 65. And reinterpret this Whenever we deposit a deposit amount less or equal to the maximum balance into an account that has initial balance 0, the resulting balance is the deposit amount  Property based testing
  • 66. Spock Genesis spock-genesis library https://github.com/Bijnagte/spock-genesis A library that helps generating values for properties
  • 67. A property based test def ”after a deposit in an account with balance 0 its balance is the deposit amount”{ when: ”deposit” def finalBalance = deposit(amount, initialBalance) then: expectedFinalBalance == finalBalance where: amount << integer(1..maxBalance).take(500) initialBalance = 0 expectedFinalBalance = amount
  • 68. Reflection time • We’ve learned more about software design • We’ve learned more about testing • We left our options open until we picked functional or OO approach • We decided step by step what’s the right next step • Still feels slow
  • 69. Practising TDD As If You Meant It
  • 70. How • Pick any kata, or a pet project • Set up a timer at 45’ • Do it every day for 10 days (continue where you left off) • Reflect on the way the design evolves, and on the design options you took •  Make every decision as deliberate as possible
  • 71. Applying TDD As If You Meant It in Production
  • 72. Do It Like Mythbusters Mythbusters
  • 73. How? • Separate a small(ish) problem. Eg: special alerts in a web application, validation in client-side code, a UI control etc.
  • 74. How? • Separate a small(ish) problem. Eg: special alerts in a web application, validation in client-side code, a UI control etc. • Start a new test suite (maybe even a new project)
  • 75. How? • Separate a small(ish) problem. Eg: special alerts in a web application, validation in client-side code, a UI control etc. • Start a new test suite (maybe even a new project) • Write the implementation using TDD as If You Meant It
  • 76. How? • Separate a small(ish) problem. Eg: special alerts in a web application, validation in client-side code, a UI control etc. • Start a new test suite (maybe even a new project) • Write the implementation using TDD as If You Meant It • When you have the production code, integrate it with the rest of the code
  • 78. Conclusions TDD As If You Meant It has helped me become more deliberate about software design. • Despite feeling slow, I found it is quite fast after practising
  • 79. Conclusions TDD As If You Meant It has helped me become more deliberate about software design. • Despite feeling slow, I found it is quite fast after practising • It helped me understand more about functional programming
  • 80. Conclusions TDD As If You Meant It has helped me become more deliberate about software design. • Despite feeling slow, I found it is quite fast after practising • It helped me understand more about functional programming • The feeling of working on a small, clean, piece of code instead of the “big” code is very liberating
  • 81. My advice Embrace constraints “I have never been forced to accept compromises but I have willingly accepted constraints” Charles Eames, Designer and Architect
  • 82. Learn more Adi’s Blog http://blog.adrianbolboaca.ro
  • 83. Thank you! I’ve been Alex Bolboacă, @alexboly, alex.bolboaca@mozaicworks.com programmer, trainer, mentor, writer at Mozaic Works Think. Design. Work Smart. https://mozaicworks.com