mockist vs. classicists tdd

33
Mockist vs. Classicist TDD Softwerkskammer Regionalgruppentreffen München 30.10.2014 David Völkel

Upload: david-voelkel

Post on 12-Jul-2015

484 views

Category:

Software


2 download

TRANSCRIPT

Mockist vs. Classicist

TDD

Softwerkskammer Regionalgruppentreffen München

30.10.2014

David Völkel

Agenda

● Theory

● Pizza

● Kata

Classicists vs. Mockists

● Who knows?

Classicists vs. Mockists

● Who knows?

● Who leverages what?

Mockists?

Classicists?

How i stumbled upon…

● #GOOS

● #IsTDDDead

● Outside-In

● Mocking

● => How work Classicist?

Classicists

● „old school“: Kent Beck, Uncle Bob, …

● state verification

● bottom-up/inside-out

● Avoid mocks when possible

Mockists

● „London School“: Steve Freeman, Nat Pryce

● XP 2000 „Endo-Testing: Unit Testing with

Mock Objects “

● OOPSLA 2004 „Mock Roles, not Objects“

● Book „Growing Object Oriented Software“

#GOOS 2009

Mockists

● ATDD

● Outside-In Design

● Hexagonal / Ports&Adapters Architecture ● also for classicists

● Mocking to isolate layers

● Interaction based testing ● „Back-door“

Architecture

● Mockist OO-style ● Message Passing/Event-Architecture

● Topology / Message flow

● „Tell don‘t ask“

● Classicist FP-style ● mutable objects encapsulating state

● pure functions & immutable value objects

● details: algorithms, logic, conditionals

Layer

UI

Domain

Data Access

DB

Domain

Hexagonal / Ports & Adapters

UI

Domain Service

Repository DB Adapter

DB

Repository Interface

Hexagonal / Ports & Adapters

Domain Service

Repository DB Mock

DB

Repository Interface

Unit Test

ATDD

From Growing Object-Oriented

Software by Nat Pryce and Steve

Freeman

Outside-In Design

UI

Domain Service

Repository DB Adapter

DB

End2End Test

Outside-In Design

UI

Domain Service

Repository DB Adapter

DB

Domain Service Interface

Unit Test

End2End Test

Outside-In Design

UI

Domain Service

Repository DB Adapter

DB

Repository Interface

Domain Service Interface

Unit Test

Unit Test

End2End Test

Outside-In Design

UI

Domain Service

Repository DB Adapter

DB

Repository Interface

Domain Service Interface

Unit Test

Unit Test

Integration

Test

End2End Test

Classicists Design

● Bottom-up ● emergent

● „TDD as if you meant it“ (YAGNI?)

● Middle ground? ● Acceptance tests => Domain

Classicist IO

out = pureFunction(in); object.changeStateBasedOn(in); out = object.getState();

● Functional

● State-based

Mockist IO: CQS

public Object myQuery() { return neighbour.query(); } when(neighbour.query()).thenReturn(in);

● Queries: Stubbing indirect input

Mockist IO: CQS

public Object myQuery() { return neighbour.query(); } when(neighbour.query()).thenReturn(in); private void myCommand() { neighbour.command(out); } verify(neighbour).command(out);

● Queries: Stubbing indirect input

● Commands: Spies check indirect output

Let‘s code!

● Content: Kata „Game of Life“ ● Phase 1: Outside-In Mockist style

● Mockless Classicist design

● Phase 2: refactor to mockless Classicist design

● Mode: Mob Programming ● 1 Driver

● N Navigators

● Variant: David = PO & facilitator

Outside-In Mockist style

Classicist Isolation

● No isolation = „front door“ ● Leaf

● Integrated test

● By design ● Context independence: parameterize

methods/constructors, values/value objects,

intermediary results

● „Functional Core, Imperative Shell“

String renderMail(String mail) { String name = userRepo.nameFor(mail); return renderMailAndName(mail, name); } @Test public void renderMail() { when(userRepo.nameFor("[email protected]")) .thenReturn("Joe Customer"); assertEquals("[email protected] <Joe Customer>", mailService.renderMail("[email protected]")); }

Isolation via mocks

String renderMail(String mail) { String name = userRepo.nameFor(mail); return renderMailAndName(mail, name); } @Test public void renderMail() { when(userRepo.nameFor("[email protected]")) .thenReturn("Joe Customer"); assertEquals("[email protected] <Joe Customer>", mailService.renderMail("[email protected]")); } @Test public void renderMail() { assertEquals("[email protected] <Joe Customer>", mailService.renderMailAndName("[email protected]", "Joe Customer")); }

Mockless isolation

Refactor mocks away

Retrospective

Bilder

von RaminusFalcon

http://commons.wikimedia.org/wiki/File:Split-

scissors.svg?uselang=de

Lizenz

Creative Commons Attribution-ShareAlike 3.0

https://creativecommons.org/licenses/by-sa/3.0/de/

TDD as if you meant it

1. Write exactly one failing test

2. Make the test pass by writing implementation code

in the test method

3. When duplication is spotted extract the

implementation from tests to:

1. a new method in the test class

2. an existing method in the test class

4. When more methods belong together extract them

into a new class

5. Refactor as required

by Adi Bolboaca