SlideShare a Scribd company logo
Designing Testable Software
OpKoKo 16.2
Ekerö October 21, 2016
@DanielDeogun
@DanielDeogun
About Me
Daniel Deogun
Coder and Quality Defender
- VP Academy, Core 3, Stockholm
- Current assignment Hi3G / Nordic Choice Hotels
- Speaker, Teacher, Lead Developer
- Author of Secure by Design, Manning publ (in progress)
- Interests: DDD, DDSec, TDD, BDD, DbC, …
@DanielDeogun
Conclusion
- Put the test hat on when designing a system
- Testing is quite hard and require a lot of good design
- You get pretty far by thinking test first
@DanielDeogun
The Spec of the New “System”
Easy to add / remove / update
functionality
Have same functionality as
the “old” system
Must be resilient
Easy to maintain
@DanielDeogun
Where do you begin?
[1]
@DanielDeogun
Test Hat On
Let’s put the test hat on
and see what we need…
[2]
@DanielDeogun
Requirement
Have same functionality as
the “old” system
@DanielDeogun
Requirement
How do we verify this?
Have same functionality as
the “old” system
@DanielDeogun
Requirement
How do we verify this?
Is there any
documentation?
Have same functionality as
the “old” system
@DanielDeogun
Requirement
How do we verify this?
Is there any
documentation?
How do we report
progress?
Have same functionality as
the “old” system
@DanielDeogun
Requirement
How do we verify this?
Is there any
documentation?
Is there a domain expert?
How do we report
progress?
Have same functionality as
the “old” system
@DanielDeogun
Requirement
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
Have same functionality as
the “old” system
@DanielDeogun
Behavior Driven Development
in a Nutshell
BDD tries to capture the behavior of a system, not how it’s implemented
@DanielDeogun
BDD in Practice
Given …
When …
Then …
scenarios
produce
Gherkin notation
@DanielDeogun
BDD in Practice
Scenarios Act As a Client
Given …
When …
Then …
public class Scenario {
public void given() {…}
public void when() {…}
public void then() {…}
}
convert to
executable test acting as a client
invokes
application
@DanielDeogun
Application Behavior Captured
by Scenario Tests
BDD Scenarios
application
@DanielDeogun
Application Behavior Captured
by Scenario Tests
BDD Scenarios
But what about dependencies
to other systems?
invokes
application
@DanielDeogun
Application Behavior Captured
by Scenario Tests
BDD Scenarios
But what about dependencies
to other systems?
invokes
application
Let’s have a look at 3 important principles…
@DanielDeogun
Dependency Inversion
Principle (DIP)
High-level modules should not depend on low-level modules. Both
should depend on abstractions.
Abstractions should not depend on details. Details should depend
on abstractions.
- https://en.wikipedia.org/wiki/Dependency_inversion_principle
@DanielDeogun
Dependency Inversion
Principle (DIP)
Dependency
Dependency implementation
abstraction
@DanielDeogun
Dependency Injection (DI)
Explained
public class Monkey {
private final Banana banana;
public Monkey() {
this.banana = new Banana();
}
…
}
Monkey depends on Banana but the
Monkey creates the banana.
public class Monkey {
private final Banana banana;
public Monkey(final Banana banana) {
this.banana = notNull(banana);
}
…
}
Monkey depends on Banana but
banana is given (injected) to Monkey
@DanielDeogun
Liskov’s
Substitution Principle
Let ϕ(x) be a property provable about objects x of type T.
Then ϕ(y) should be true for objects y of type S where S is a subtype of T.
- Barbara Liskov and Jeannette Wing [3]
@DanielDeogun
LSP - “For Dummies”
If C is a subtype of P, then objects of type P may be replaced by objects of
type C without violating behavior or invariants
- Common Sense
class C extends P {…}
final P p = new C();
@DanielDeogun
The Beautiful Trinity
DIP + DI + LSP = True
[6]
@DanielDeogun
DIP, DI, and LSP
Allows Isolated Testing
Let’s use DI to inject dependencies
Let’s use DIP to remove dependencies to low
level implementations
Let’s use LSP to ensure invariants and
behavior
dependency
abstraction
@DanielDeogun
Pros & Cons
BDD & Spec by Example
+ Easy to verify business rules and expected behavior
+ A good way to learn how the system works
+ Creates confidence
- Deciding what to test may be hard
- Feature driven scenario organization may create duplicated tests
- Requires deep domain knowledge
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
Have same functionality as
the “old” system
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
√
Have same functionality as
the “old” system
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
√
√?
Have same functionality as
the “old” system
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
√
√
√?
Have same functionality as
the “old” system
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
√
√?√
√?
Have same functionality as
the “old” system
@DanielDeogun
Evaluation
How do we verify this?
Is there any
documentation?
Is there a domain expert?
Do we want “exactly”
the same behavior?
How do we report
progress?
√
√
√
?√
√?
Have same functionality as
the “old” system
@DanielDeogun
Requirement
Easy to add / remove / update
functionality
Easy to maintain
@DanielDeogun
Requirement
Easy to add / remove / update
functionality
How do we avoid breaking things?
Easy to maintain
@DanielDeogun
Requirement
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
@DanielDeogun
Requirement
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
What does easy to maintain
mean?
@DanielDeogun
Test Driven Development
RED
GREEN
REFACTOR
Prove need
Smallest
code change
Improve
TDD tend to focus on how something is
implemented rather than its behavior
A good practice is to use BDD when doing TDD
@DanielDeogun
TDD Á la BDD
public void test_ticker() {
Ticker ticker = new Ticker();
ticker.increment();
assertEquals(1, ticker.value());
}
TDD
@DanielDeogun
TDD Á la BDD
public void test_ticker() {
Ticker ticker = new Ticker();
ticker.increment();
assertEquals(1, ticker.value());
}
TDD
public void should_increment_ticker() {
givenTickerWithRandomStart();
int expectedValue =
ticker.value() +
ticker.incrementStep();
ticker.increment();
thenTickerIsIncrementedTo(expectedValue);
}
TDD á la BDD
@DanielDeogun
TDD Á la BDD
public void test_ticker() {
Ticker ticker = new Ticker();
ticker.increment();
assertEquals(1, ticker.value());
}
!
- Never verify more than one behavior in each test
- Don’t use a common set up method
TDD
public void should_increment_ticker() {
givenTickerWithRandomStart();
int expectedValue =
ticker.value() +
ticker.incrementStep();
ticker.increment();
thenTickerIsIncrementedTo(expectedValue);
}
TDD á la BDD
@DanielDeogun
Mocks
“…mock objects are simulated objects that mimic the behavior of real
objects in controlled ways. A programmer typically creates a mock object to
test the behavior of some other object, …”
https://en.wikipedia.org/wiki/Mock_object
@DanielDeogun
Use DI to Inject Mocks
private final List<Item> items = mock(List.class);

private final ShoppingCart shoppingCart = new ShoppingCart(items);
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean add(final Item item) {

return items.add(notNull(item));

}



public boolean remove(final Item item) {

return items.remove(notNull(item));

}

…
@DanielDeogun
The Great Frustration
Incorrect mocking makes you spend more time updating test
code than production code
And the reason is…
@DanielDeogun
The Great Frustration
Incorrect mocking makes you spend more time updating test
code than production code
And the reason is…
Nobody puts Barbra in the corner!
@DanielDeogun
Violating LSP
Yield Brittle Tests
private final List<Item> items = mock(List.class);

private final ShoppingCart shoppingCart = new ShoppingCart(items);
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean add(final Item item) {

return items.add(notNull(item));

}



public boolean remove(final Item item) {

return items.remove(notNull(item));

}

…
@DanielDeogun
Violating LSP
Yield Brittle Tests
@Test

public void should_remove_item() {

final Item coke = new Coke();

BDDMockito.given(items.remove(coke)).willReturn(true);



final boolean result = shoppingCart.remove(coke);



assertTrue(result);

}
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean remove(final Item item) {
return items.remove(notNull(item));
}

…
@DanielDeogun
Violating LSP
Yield Brittle Tests
@Test

public void should_remove_item() {

final Item coke = new Coke();

BDDMockito.given(items.remove(coke)).willReturn(true);



final boolean result = shoppingCart.remove(coke);



assertTrue(result);

}
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean remove(final Item item) {
return items.remove(notNull(item));
}

…
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean remove(final Item item) {

return items.removeAll(items.stream()

.filter(i -> i.equals(item))

.collect(toList()));

}
@DanielDeogun
Violating LSP
Yield Brittle Tests
@Test

public void should_remove_item() {

final Item coke = new Coke();

BDDMockito.given(items.remove(coke)).willReturn(true);



final boolean result = shoppingCart.remove(coke);



assertTrue(result);

}
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean remove(final Item item) {
return items.remove(notNull(item));
}

…
public class ShoppingCart {

private final List<Item> items;



public ShoppingCart(final List<Item> items) {

this.items = notNull(items);

}



public boolean remove(final Item item) {

return items.removeAll(items.stream()

.filter(i -> i.equals(item))

.collect(toList()));

}
java.lang.NullPointerException
@DanielDeogun
Analysis
The “items” mock doesn’t satisfy LSP
Invoking an unmocked method on the items object causes a failure
Beware: Mockito uses default mocking behavior on some types
(e.g. List, int, boolean, etc)
private final List<Item> items = mock(List.class);

private final ShoppingCart shoppingCart = new ShoppingCart(items);
@DanielDeogun
Tip of the Day
Make domain classes final to “prevent“ mocking!
[8]
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class se.omegapoint.opkoko.MyDomainClass
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
@DanielDeogun
Branch By Code
Using Feature Toggles
http://martinfowler.com/articles/feature-toggles.html
@DanielDeogun
Branch By Code
Using Feature Toggles
Release toggles
• Compile time dependency
• Ex: use DI and start app with different configuration
Ops toggles
• Runtime dependency
• Ex: special API only available for operations
Experiment toggles
• Runtime dependency used for A/B testing
• Ex: toggle is based on user information
Permission toggles
• Runtime dependency
• Ex: Toggle is based on payment information
@DanielDeogun
How Do Feature Toggles
Affect Testing?
Release toggles
• test what’s enabled (in production)
Ops toggles
• make sure they only work for operations
Experiment toggles
• test the selection algorithm
Permission toggles
• test applicability
We cannot test every possible combination
Make an educated choice
@DanielDeogun
Evaluation
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
What does easy to maintain
mean?
@DanielDeogun
Evaluation
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
What does easy to maintain
mean?
√
@DanielDeogun
Evaluation
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
What does easy to maintain
mean?
√
√
@DanielDeogun
Evaluation
Easy to add / remove / update
functionality
How do we avoid breaking things?
How do we design for change?
Easy to maintain
What does easy to maintain
mean?
√√?
√
@DanielDeogun
Requirement
Must be resilient
@DanielDeogun
Requirement
How do we measure “resilience?”
Must be resilient
@DanielDeogun
Requirement
How do we measure “resilience?”
How do we test resilience?
Must be resilient
@DanielDeogun
Requirement
How do we measure “resilience?”
How do we test resilience?
Can we find the “upper bound?”
Must be resilient
@DanielDeogun
System Integration Resilience
@DanielDeogun
Circuit Breaker
“A circuit breaker is an automatically operated electrical switch designed
to protect an electrical circuit from damage caused by overcurrent or
overload or short circuit.”
- https://en.wikipedia.org/wiki/Circuit_breaker
@DanielDeogun
Circuit Breakers
Avoid Killing Backend
circuit breakers
@DanielDeogun
Schematic view of a
Circuit Breaker
- Release It! Michael Nygard, The Pragmatic Bookshelf
@DanielDeogun
Bulkhead Pattern
https://github.com/Netflix/Hystrix/wiki/How-it-Works#Threads
[9]
@DanielDeogun
Separate Thread Pools
Avoid Cascading Failures
circuit breakers
Separate thread pools
@DanielDeogun
Request Collapsing Pattern
https://github.com/Netflix/Hystrix/wiki/How-it-Works#RequestCollapsing
@DanielDeogun
“Internal” Resilience
[5]
Bad input data
Corrupt responses
Design by Contract
Message driven
Domain Driven Design
Null values
Default values
Immutability
Concurrency
@DanielDeogun
Hostile Environment
Imagine an environment whose only purpose is to
bring your application to its knees
Each endpoint is a potential “threat”
Put your application under heavy load, inject bad
input, return corrupt data, etc
Make this a stage in your delivery pipeline
Monitor memory consumption, response times, etc
@DanielDeogun
Evaluation
How do we measure “resilience?”
How do we test resilience?
Must be resilient
Can we find the “upper bound?”
@DanielDeogun
Evaluation
How do we measure “resilience?”
How do we test resilience?
Must be resilient
Can we find the “upper bound?”
√?
@DanielDeogun
Evaluation
How do we measure “resilience?”
How do we test resilience?
Must be resilient
√
Can we find the “upper bound?”
√?
@DanielDeogun
Evaluation
How do we measure “resilience?”
How do we test resilience?
Must be resilient
√
√
Can we find the “upper bound?”
√?
@DanielDeogun
The Spec of the New “System”
Easy to add / remove / update
functionality
Have same functionality as
the “old” system
Must be resilient
Easy to maintain
@DanielDeogun
Conclusion
- Put the test hat on when designing a system
- Testing is quite hard and require a lot of good design
- You get pretty far by thinking test first
@DanielDeogun
Q & A
[7]
@DanielDeogun
Thanks
@DanielDeogun
@DanielDeogun
References
[1] Torsten, math teacher, https://flic.kr/p/ndFN4Q License: https://creativecommons.org/licenses/by/2.0/
[2] Emily Moe, IMG_7788, https://flic.kr/p/aH4rwk, License: https://creativecommons.org/licenses/by-nd/2.0/
[3] Liskov’s Substitution Principle, Wikipedia, https://en.wikipedia.org/wiki/Liskov_substitution_principle
[4] Tsutomu Takasu, Horse racing event, https://flic.kr/p/6Yy3NZ, License: https://creativecommons.org/licenses/by/2.0/
[5] http://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Emblem-evil-computer.svg/500px-Emblem-evil-computer.svg.png
[6] Huey, Dewey, and Louie Duck, drawn by cartoonist Carl Barks, https://en.wikipedia.org/wiki/File:Louie_Dewey_and_Huey.png
[7] Questions, https://flic.kr/p/9ksxQa] by Damián Navas, License: https://creativecommons.org/licenses/by-nc-nd/2.0/
[8] Chuck Coker, Light Bulb No. 1, https://flic.kr/p/66KLFn, License: https://creativecommons.org/licenses/by-nd/2.0/
[9] DRVMX, Titantic, https://flic.kr/p/gNLK84, License: https://creativecommons.org/licenses/by-nd/2.0/

More Related Content

PDF
Working Effectively with Legacy Code
PPTX
Mockito para tus pruebas unitarias
PDF
ISSTA 2017 Impact Paper Award Presentation
PDF
Software Testing:
 A Research Travelogue 
(2000–2014)
PDF
Evaluating the Usefulness of IR-Based Fault LocalizationTechniques
PDF
PDF
Testing the unpredictable
PPT
Software Design for Testability
Working Effectively with Legacy Code
Mockito para tus pruebas unitarias
ISSTA 2017 Impact Paper Award Presentation
Software Testing:
 A Research Travelogue 
(2000–2014)
Evaluating the Usefulness of IR-Based Fault LocalizationTechniques
Testing the unpredictable
Software Design for Testability

Similar to Designing Testable Software (20)

PDF
Dawn - Actionscript Library
PDF
Clean Code 2
PPT
01-introductionto Object ooriented Programming in JAVA CS.ppt
PPT
01-introduction OOPS concepts in C++ JAVA
ODP
New Ideas for Old Code - Greach
PDF
Keep it Secret, Keep it Safe - Docker Secrets and DI
ODP
Dependency Injection in Spring in 10min
PPTX
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
PPTX
DevSecCon SG 2018 Fabian Presentation Slides
PDF
DPCL: a Language Template for Normative Specifications
PDF
Thinking hard about_python
PDF
Splunk September 2023 User Group PDX.pdf
PDF
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
PDF
Devoxx PL 2017 - Cracking the Code to Secure Software
PDF
Design For Testability
PPTX
Tdd & clean code
PPTX
Breaking Dependencies to Allow Unit Testing
PDF
TeelTech - Advancing Mobile Device Forensics (online version)
PDF
Bdd and-testing
PDF
Behaviour Driven Development and Thinking About Testing
 
Dawn - Actionscript Library
Clean Code 2
01-introductionto Object ooriented Programming in JAVA CS.ppt
01-introduction OOPS concepts in C++ JAVA
New Ideas for Old Code - Greach
Keep it Secret, Keep it Safe - Docker Secrets and DI
Dependency Injection in Spring in 10min
How I Learned to Stop Worrying and Love Legacy Code - Ox:Agile 2018
DevSecCon SG 2018 Fabian Presentation Slides
DPCL: a Language Template for Normative Specifications
Thinking hard about_python
Splunk September 2023 User Group PDX.pdf
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
Devoxx PL 2017 - Cracking the Code to Secure Software
Design For Testability
Tdd & clean code
Breaking Dependencies to Allow Unit Testing
TeelTech - Advancing Mobile Device Forensics (online version)
Bdd and-testing
Behaviour Driven Development and Thinking About Testing
 
Ad

More from Omegapoint Academy (14)

PDF
Domain Primitives in Action - DataTjej 2018
PDF
Secure by Design - Jfokus 2018 tutorial
PDF
Domain Primitives In Action - Explore DDD 2017
PDF
Making Software Secure by Design
PDF
Domain driven security_java_zone2016
PDF
Domain Driven Security Jfokus 2016
PDF
Arm yourself with Domain Driven Security. It's time to slay some security trolls
PDF
Designing software with security in mind
PDF
Failing Continuous Delivery, Devoxx Poland, 2015
PDF
Designing software with security in mind?
PPTX
Studentkonferens 2015 - Alla pratar om risker, men vad är det?
PDF
Studentkonferens 2015 1 + 1 = 1 (The Omegapoint Way)
PPTX
Studenkonferens 2015 - Craftsmanship
PPTX
Agile Enterprise: frukostseminarium
Domain Primitives in Action - DataTjej 2018
Secure by Design - Jfokus 2018 tutorial
Domain Primitives In Action - Explore DDD 2017
Making Software Secure by Design
Domain driven security_java_zone2016
Domain Driven Security Jfokus 2016
Arm yourself with Domain Driven Security. It's time to slay some security trolls
Designing software with security in mind
Failing Continuous Delivery, Devoxx Poland, 2015
Designing software with security in mind?
Studentkonferens 2015 - Alla pratar om risker, men vad är det?
Studentkonferens 2015 1 + 1 = 1 (The Omegapoint Way)
Studenkonferens 2015 - Craftsmanship
Agile Enterprise: frukostseminarium
Ad

Recently uploaded (20)

PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Nekopoi APK 2025 free lastest update
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
medical staffing services at VALiNTRY
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
L1 - Introduction to python Backend.pptx
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
history of c programming in notes for students .pptx
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPT
Introduction Database Management System for Course Database
PDF
top salesforce developer skills in 2025.pdf
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Nekopoi APK 2025 free lastest update
Wondershare Filmora 15 Crack With Activation Key [2025
medical staffing services at VALiNTRY
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
L1 - Introduction to python Backend.pptx
VVF-Customer-Presentation2025-Ver1.9.pptx
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Odoo Companies in India – Driving Business Transformation.pdf
Digital Systems & Binary Numbers (comprehensive )
history of c programming in notes for students .pptx
Navsoft: AI-Powered Business Solutions & Custom Software Development
Introduction Database Management System for Course Database
top salesforce developer skills in 2025.pdf
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Upgrade and Innovation Strategies for SAP ERP Customers
How to Choose the Right IT Partner for Your Business in Malaysia

Designing Testable Software

  • 1. Designing Testable Software OpKoKo 16.2 Ekerö October 21, 2016 @DanielDeogun
  • 2. @DanielDeogun About Me Daniel Deogun Coder and Quality Defender - VP Academy, Core 3, Stockholm - Current assignment Hi3G / Nordic Choice Hotels - Speaker, Teacher, Lead Developer - Author of Secure by Design, Manning publ (in progress) - Interests: DDD, DDSec, TDD, BDD, DbC, …
  • 3. @DanielDeogun Conclusion - Put the test hat on when designing a system - Testing is quite hard and require a lot of good design - You get pretty far by thinking test first
  • 4. @DanielDeogun The Spec of the New “System” Easy to add / remove / update functionality Have same functionality as the “old” system Must be resilient Easy to maintain
  • 6. @DanielDeogun Test Hat On Let’s put the test hat on and see what we need… [2]
  • 8. @DanielDeogun Requirement How do we verify this? Have same functionality as the “old” system
  • 9. @DanielDeogun Requirement How do we verify this? Is there any documentation? Have same functionality as the “old” system
  • 10. @DanielDeogun Requirement How do we verify this? Is there any documentation? How do we report progress? Have same functionality as the “old” system
  • 11. @DanielDeogun Requirement How do we verify this? Is there any documentation? Is there a domain expert? How do we report progress? Have same functionality as the “old” system
  • 12. @DanielDeogun Requirement How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? Have same functionality as the “old” system
  • 13. @DanielDeogun Behavior Driven Development in a Nutshell BDD tries to capture the behavior of a system, not how it’s implemented
  • 14. @DanielDeogun BDD in Practice Given … When … Then … scenarios produce Gherkin notation
  • 15. @DanielDeogun BDD in Practice Scenarios Act As a Client Given … When … Then … public class Scenario { public void given() {…} public void when() {…} public void then() {…} } convert to executable test acting as a client invokes application
  • 16. @DanielDeogun Application Behavior Captured by Scenario Tests BDD Scenarios application
  • 17. @DanielDeogun Application Behavior Captured by Scenario Tests BDD Scenarios But what about dependencies to other systems? invokes application
  • 18. @DanielDeogun Application Behavior Captured by Scenario Tests BDD Scenarios But what about dependencies to other systems? invokes application Let’s have a look at 3 important principles…
  • 19. @DanielDeogun Dependency Inversion Principle (DIP) High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. - https://en.wikipedia.org/wiki/Dependency_inversion_principle
  • 21. @DanielDeogun Dependency Injection (DI) Explained public class Monkey { private final Banana banana; public Monkey() { this.banana = new Banana(); } … } Monkey depends on Banana but the Monkey creates the banana. public class Monkey { private final Banana banana; public Monkey(final Banana banana) { this.banana = notNull(banana); } … } Monkey depends on Banana but banana is given (injected) to Monkey
  • 22. @DanielDeogun Liskov’s Substitution Principle Let ϕ(x) be a property provable about objects x of type T. Then ϕ(y) should be true for objects y of type S where S is a subtype of T. - Barbara Liskov and Jeannette Wing [3]
  • 23. @DanielDeogun LSP - “For Dummies” If C is a subtype of P, then objects of type P may be replaced by objects of type C without violating behavior or invariants - Common Sense class C extends P {…} final P p = new C();
  • 25. @DanielDeogun DIP, DI, and LSP Allows Isolated Testing Let’s use DI to inject dependencies Let’s use DIP to remove dependencies to low level implementations Let’s use LSP to ensure invariants and behavior dependency abstraction
  • 26. @DanielDeogun Pros & Cons BDD & Spec by Example + Easy to verify business rules and expected behavior + A good way to learn how the system works + Creates confidence - Deciding what to test may be hard - Feature driven scenario organization may create duplicated tests - Requires deep domain knowledge
  • 27. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? Have same functionality as the “old” system
  • 28. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? √ Have same functionality as the “old” system
  • 29. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? √ √? Have same functionality as the “old” system
  • 30. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? √ √ √? Have same functionality as the “old” system
  • 31. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? √ √?√ √? Have same functionality as the “old” system
  • 32. @DanielDeogun Evaluation How do we verify this? Is there any documentation? Is there a domain expert? Do we want “exactly” the same behavior? How do we report progress? √ √ √ ?√ √? Have same functionality as the “old” system
  • 33. @DanielDeogun Requirement Easy to add / remove / update functionality Easy to maintain
  • 34. @DanielDeogun Requirement Easy to add / remove / update functionality How do we avoid breaking things? Easy to maintain
  • 35. @DanielDeogun Requirement Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain
  • 36. @DanielDeogun Requirement Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain What does easy to maintain mean?
  • 37. @DanielDeogun Test Driven Development RED GREEN REFACTOR Prove need Smallest code change Improve TDD tend to focus on how something is implemented rather than its behavior A good practice is to use BDD when doing TDD
  • 38. @DanielDeogun TDD Á la BDD public void test_ticker() { Ticker ticker = new Ticker(); ticker.increment(); assertEquals(1, ticker.value()); } TDD
  • 39. @DanielDeogun TDD Á la BDD public void test_ticker() { Ticker ticker = new Ticker(); ticker.increment(); assertEquals(1, ticker.value()); } TDD public void should_increment_ticker() { givenTickerWithRandomStart(); int expectedValue = ticker.value() + ticker.incrementStep(); ticker.increment(); thenTickerIsIncrementedTo(expectedValue); } TDD á la BDD
  • 40. @DanielDeogun TDD Á la BDD public void test_ticker() { Ticker ticker = new Ticker(); ticker.increment(); assertEquals(1, ticker.value()); } ! - Never verify more than one behavior in each test - Don’t use a common set up method TDD public void should_increment_ticker() { givenTickerWithRandomStart(); int expectedValue = ticker.value() + ticker.incrementStep(); ticker.increment(); thenTickerIsIncrementedTo(expectedValue); } TDD á la BDD
  • 41. @DanielDeogun Mocks “…mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A programmer typically creates a mock object to test the behavior of some other object, …” https://en.wikipedia.org/wiki/Mock_object
  • 42. @DanielDeogun Use DI to Inject Mocks private final List<Item> items = mock(List.class);
 private final ShoppingCart shoppingCart = new ShoppingCart(items); public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean add(final Item item) {
 return items.add(notNull(item));
 }
 
 public boolean remove(final Item item) {
 return items.remove(notNull(item));
 }
 …
  • 43. @DanielDeogun The Great Frustration Incorrect mocking makes you spend more time updating test code than production code And the reason is…
  • 44. @DanielDeogun The Great Frustration Incorrect mocking makes you spend more time updating test code than production code And the reason is… Nobody puts Barbra in the corner!
  • 45. @DanielDeogun Violating LSP Yield Brittle Tests private final List<Item> items = mock(List.class);
 private final ShoppingCart shoppingCart = new ShoppingCart(items); public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean add(final Item item) {
 return items.add(notNull(item));
 }
 
 public boolean remove(final Item item) {
 return items.remove(notNull(item));
 }
 …
  • 46. @DanielDeogun Violating LSP Yield Brittle Tests @Test
 public void should_remove_item() {
 final Item coke = new Coke();
 BDDMockito.given(items.remove(coke)).willReturn(true);
 
 final boolean result = shoppingCart.remove(coke);
 
 assertTrue(result);
 } public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean remove(final Item item) { return items.remove(notNull(item)); }
 …
  • 47. @DanielDeogun Violating LSP Yield Brittle Tests @Test
 public void should_remove_item() {
 final Item coke = new Coke();
 BDDMockito.given(items.remove(coke)).willReturn(true);
 
 final boolean result = shoppingCart.remove(coke);
 
 assertTrue(result);
 } public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean remove(final Item item) { return items.remove(notNull(item)); }
 … public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean remove(final Item item) {
 return items.removeAll(items.stream()
 .filter(i -> i.equals(item))
 .collect(toList()));
 }
  • 48. @DanielDeogun Violating LSP Yield Brittle Tests @Test
 public void should_remove_item() {
 final Item coke = new Coke();
 BDDMockito.given(items.remove(coke)).willReturn(true);
 
 final boolean result = shoppingCart.remove(coke);
 
 assertTrue(result);
 } public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean remove(final Item item) { return items.remove(notNull(item)); }
 … public class ShoppingCart {
 private final List<Item> items;
 
 public ShoppingCart(final List<Item> items) {
 this.items = notNull(items);
 }
 
 public boolean remove(final Item item) {
 return items.removeAll(items.stream()
 .filter(i -> i.equals(item))
 .collect(toList()));
 } java.lang.NullPointerException
  • 49. @DanielDeogun Analysis The “items” mock doesn’t satisfy LSP Invoking an unmocked method on the items object causes a failure Beware: Mockito uses default mocking behavior on some types (e.g. List, int, boolean, etc) private final List<Item> items = mock(List.class);
 private final ShoppingCart shoppingCart = new ShoppingCart(items);
  • 50. @DanielDeogun Tip of the Day Make domain classes final to “prevent“ mocking! [8] org.mockito.exceptions.base.MockitoException: Cannot mock/spy class se.omegapoint.opkoko.MyDomainClass Mockito cannot mock/spy following: - final classes - anonymous classes - primitive types
  • 51. @DanielDeogun Branch By Code Using Feature Toggles http://martinfowler.com/articles/feature-toggles.html
  • 52. @DanielDeogun Branch By Code Using Feature Toggles Release toggles • Compile time dependency • Ex: use DI and start app with different configuration Ops toggles • Runtime dependency • Ex: special API only available for operations Experiment toggles • Runtime dependency used for A/B testing • Ex: toggle is based on user information Permission toggles • Runtime dependency • Ex: Toggle is based on payment information
  • 53. @DanielDeogun How Do Feature Toggles Affect Testing? Release toggles • test what’s enabled (in production) Ops toggles • make sure they only work for operations Experiment toggles • test the selection algorithm Permission toggles • test applicability We cannot test every possible combination Make an educated choice
  • 54. @DanielDeogun Evaluation Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain What does easy to maintain mean?
  • 55. @DanielDeogun Evaluation Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain What does easy to maintain mean? √
  • 56. @DanielDeogun Evaluation Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain What does easy to maintain mean? √ √
  • 57. @DanielDeogun Evaluation Easy to add / remove / update functionality How do we avoid breaking things? How do we design for change? Easy to maintain What does easy to maintain mean? √√? √
  • 59. @DanielDeogun Requirement How do we measure “resilience?” Must be resilient
  • 60. @DanielDeogun Requirement How do we measure “resilience?” How do we test resilience? Must be resilient
  • 61. @DanielDeogun Requirement How do we measure “resilience?” How do we test resilience? Can we find the “upper bound?” Must be resilient
  • 63. @DanielDeogun Circuit Breaker “A circuit breaker is an automatically operated electrical switch designed to protect an electrical circuit from damage caused by overcurrent or overload or short circuit.” - https://en.wikipedia.org/wiki/Circuit_breaker
  • 65. @DanielDeogun Schematic view of a Circuit Breaker - Release It! Michael Nygard, The Pragmatic Bookshelf
  • 67. @DanielDeogun Separate Thread Pools Avoid Cascading Failures circuit breakers Separate thread pools
  • 69. @DanielDeogun “Internal” Resilience [5] Bad input data Corrupt responses Design by Contract Message driven Domain Driven Design Null values Default values Immutability Concurrency
  • 70. @DanielDeogun Hostile Environment Imagine an environment whose only purpose is to bring your application to its knees Each endpoint is a potential “threat” Put your application under heavy load, inject bad input, return corrupt data, etc Make this a stage in your delivery pipeline Monitor memory consumption, response times, etc
  • 71. @DanielDeogun Evaluation How do we measure “resilience?” How do we test resilience? Must be resilient Can we find the “upper bound?”
  • 72. @DanielDeogun Evaluation How do we measure “resilience?” How do we test resilience? Must be resilient Can we find the “upper bound?” √?
  • 73. @DanielDeogun Evaluation How do we measure “resilience?” How do we test resilience? Must be resilient √ Can we find the “upper bound?” √?
  • 74. @DanielDeogun Evaluation How do we measure “resilience?” How do we test resilience? Must be resilient √ √ Can we find the “upper bound?” √?
  • 75. @DanielDeogun The Spec of the New “System” Easy to add / remove / update functionality Have same functionality as the “old” system Must be resilient Easy to maintain
  • 76. @DanielDeogun Conclusion - Put the test hat on when designing a system - Testing is quite hard and require a lot of good design - You get pretty far by thinking test first
  • 79. @DanielDeogun References [1] Torsten, math teacher, https://flic.kr/p/ndFN4Q License: https://creativecommons.org/licenses/by/2.0/ [2] Emily Moe, IMG_7788, https://flic.kr/p/aH4rwk, License: https://creativecommons.org/licenses/by-nd/2.0/ [3] Liskov’s Substitution Principle, Wikipedia, https://en.wikipedia.org/wiki/Liskov_substitution_principle [4] Tsutomu Takasu, Horse racing event, https://flic.kr/p/6Yy3NZ, License: https://creativecommons.org/licenses/by/2.0/ [5] http://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Emblem-evil-computer.svg/500px-Emblem-evil-computer.svg.png [6] Huey, Dewey, and Louie Duck, drawn by cartoonist Carl Barks, https://en.wikipedia.org/wiki/File:Louie_Dewey_and_Huey.png [7] Questions, https://flic.kr/p/9ksxQa] by Damián Navas, License: https://creativecommons.org/licenses/by-nc-nd/2.0/ [8] Chuck Coker, Light Bulb No. 1, https://flic.kr/p/66KLFn, License: https://creativecommons.org/licenses/by-nd/2.0/ [9] DRVMX, Titantic, https://flic.kr/p/gNLK84, License: https://creativecommons.org/licenses/by-nd/2.0/