FAKE IT OUTSIDE-IN TDD
David Völkel
08.06.2018 @ IT.A.K.E Unconference
@DAVIDVOELKEL
@codecentric
@softwerkskammer
#TDD
INFLUENCES
2003 Kent Beck’s "Fake It" Pattern
2009 #GOOS’s "Outside-In" Design
2013 Emily Bache 

"Outside-In development with Double Loop TDD"
2014 Justin Searls "The Failures of 'Intro to TDD'"
COMBINATION
2015 Dimitry Polivaev Outside-In with faked Data
2016 SoCraTes DE Outside-In Fake It Session
2017 Refinement
INFLUENCES
2003 Kent Beck’s "Fake It" Pattern
2009 #GOOS’s "Outside-In" Design
2013 Emily Bache 

"Outside-In development with Double Loop TDD"
2014 Justin Searls "The Failures of 'Intro to TDD'"
COMBINATION
2015 Dimitry Polivaev Outside-In with faked Data
2016 SoCraTes DE Outside-In Fake It Session
2017 Refinement
INFLUENCES
2003 Kent Beck’s "Fake It" Pattern
2009 #GOOS’s "Outside-In" Design
COMBINATION
FAKE IT OUTSIDE-IN TDD
FAKE IT OUTSIDE-IN TDD
INFLUENCES
2003 Kent Beck’s "Fake It" Pattern
2009 #GOOS’s "Outside-In" Design
2013 Emily Bache 

"Outside-In development with Double Loop TDD"
2014 Justin Searls "The Failures of 'Intro to TDD'"
2017 Llewelyn Falco „Extreme: Fake it Till you Make It“
FAKE IT OUTSIDE-IN TDD
WHY?
Outside-In => YAGNI free design
WHY?
Outside-In => YAGNI free design
Avoid mocking drawbacks
- Readability
- Refactorability
WHY?
Outside-In => YAGNI free design
Avoid mocking drawbacks
- Readability
- Refactorability
Later: Smaller steps
AGENDA
Theory
Building Blocks
Fake It Outside-In
Practice
Mob Programming Session
Reflect
Retro
Trade-Offs
BUILDING BLOCKS
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
*"Integration Operation Segregation Principle", Ralf Westphal
"Die kniffligen Fälle beim Testen - Sichtbarkeit", Stefan Lieser
*
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
Account account = customer.account();
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
String content = "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
mailService.sendMail(email, content);
}
OPERATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
Account account = customer.account();
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
String content = "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
mailService.sendMail(email, content);
}
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
INTEGRATION
INTEGRATION
OPERATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
Account account = customer.account();
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
String content = "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
mailService.sendMail(email, content);
}
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
INTEGRATION
INTEGRATION
OPERATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
Account account = customer.account();
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
String content = "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
mailService.sendMail(email, content);
}
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
OPERATION
INTEGRATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderMessage(customer, customer.account());
mailService.sendMail(email, content);
}
private String renderMessage(Customer customer, Account account) {
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
return "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
}
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderMessage(customer, customer.account());
mailService.sendMail(email, content);
}
private String renderMessage(Customer customer, Account account) {
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
return "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
}
TESTS?
OPERATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderMessage(customer, customer.account());
mailService.sendMail(email, content);
}
private String renderMessage(Customer customer, Account account) {
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
return "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
}
TESTS?
N UNITTESTS
INTEGRATION
OPERATION
public void sendDiscountMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderMessage(customer, customer.account());
mailService.sendMail(email, content);
}
private String renderMessage(Customer customer, Account account) {
String discount = account == FREE ? "no" :
account == BASE ? "a 10%" :
account == PREMIUM ? "a 25%" :
"-ERROR-";
return "Hello " + customer.getName() + ",nn" +
"This week you get " + discount + " discount " +
"on all our products.nn" +
"Best Regards,n" + "ACME Customer Service";
}
TESTS?1 INTEGRATION TEST (or MOCKING TEST)
N UNITTESTS
GREEN BAR PATTERNS*
Obvious Implementation
Fake it (until you make it)
Triangulation
* Kent Beck in "TDD by Example"
GREEN BAR PATTERNS
Obvious Implementation
Fake it
Triangulation
Trade-Off
Complexity
GREEN BAR PATTERNS
DEMO
SWEET SPOT
Trivial
GREEN BAR PATTERNS
Obvious Implementation
Fake it
Triangulation
SWEET SPOT
Trivial
Structure
GREEN BAR PATTERNS
Obvious Implementation
Fake it
Triangulation
SWEET SPOT
Trivial
Structure
Logic
GREEN BAR PATTERNS
Obvious Implementation
Fake it
Triangulation
PREPARATORY REFACTORINGS*
*"An example of preparatory refactoring", Martin Fowler
PREPARATORY REFACTORINGS*
*"An example of preparatory refactoring", Martin Fowler
"GREEN" PHASE TRIANGULATION
Implementation Run Test
"Green Phase"
LIMIT YOUR TIME IN RED
"Green Phase"
Implementation Run Test
LIMIT YOUR TIME IN RED
"Green Phase"
Implementation Run Test
Implementation Run TestPreparatory Refactoring
PREPARATORY REFACTORINGS
DEMO
CALCULATE
BACKWARDS
DEMO
Acceptance Test
UI
Persistence
OUTSIDE-IN
Acceptance Test
UI
Persistence
OUTSIDE-IN & MOCKS
Unit test
Mock
OUTSIDE-IN & MOCKS
Unit Test
OUTSIDE-IN & MOCKS
Acceptance Test
UI
Persistence
OUTSIDE-IN & MOCKS
Non trivial
Acceptance Test
OUTSIDE-IN & FAKE IT
Acceptance Test
Faked Result
OUTSIDE-IN & FAKE IT
Acceptance Test
Fake
Fake
OUTSIDE-IN & FAKE IT
Acceptance Test Drive Structure
through Refactoring
OUTSIDE-IN & FAKE IT
OUTSIDE-IN & FAKE IT
Acceptance Test
Unit Test
Fill logic with
triangulation
OUTSIDE-IN & FAKE IT
Acceptance Test Unit Test
OUTSIDE-IN & FAKE IT
INTEGRATION
Fake It
Triangulation
OPERATION
Start with
• comprehensive 

Acceptance Test
• faked result
Drive structure by refactoring
Drive logic by unit tests
OUTSIDE-IN & FAKE IT
INTEGRATION
Fake It
Triangulation
OPERATION
Start with
• comprehensive 

Acceptance Test
• faked result
Drive structure by refactoring
Drive logic by unit tests
DIAMOND KATA
FAKE IT OUTSIDE-IN
DEMO
MOB PROGRAMMING
DIAMOND KATA
MOB SESSION
KATA
Continue Diamond Kata ("Upper Left Corner“)
Fake it Outside-In constraint
https://github.com/davidvoelkel/diamond-kata
RETROSPECTIVE
Observations?
RETROSPECTIVE
Observations?
Strenghts / Weaknesses?
TRADE-OFFS
FAKE IT VS
OUTSIDE-IN & MOCKS
TRIANGULATION
CONDITIONAL INTERACTIONS
Mocking when IOSP not possible
public String signup(String username) throws Exception {
if(userDB.findUserBy(username) == null) {
userDB.createUser(new User(username));
return "Welcome " + username;
} else {
return "Username ' " + username + "' "
+ "already taken, please choose another";
}
}
COUPLING OUTSIDE-IN
Mocking Fake It
Decoupling Refactorability
DATA GUIDES STRUCTURE
Triangulation Fake It
Structure Cumbersome Data guides well
# BRANCHES
Triangulation Fake It
# N 1
More confidence
More effort
# BRANCHES
Triangulation Fake It
# N 1
Fake data easy to forget
Omitting cases is
tempting
TIME IN GREEN
Triangulation
Prep Refactoring
Triangulation
Fake It
WHY?
Outside-In
=> YAGNI free design
Without mocking drawbacks
WHY?
Outside-In
=> YAGNI free design
Without mocking drawbacks
Vs Triangulation
More time in GREEN
Better Design Guidance
THANKS
LICENSE
Creative Commons Attribution-ShareAlike 3.0
IMAGES
Most are Public Domain except theses
Creative Commons with attributions:
"Unstruttalbrücke" by Störfix
From State Library of Queensland

Fake it Outside-In TDD IT.A.K.E 2018