Top Banner
When TDD Goes Awry Clueless tests, infesting mocks and other horrors... A voyage into today Java Enterprise worse practices. Uberto Barbini @ramtop h0ps://github.com/uberto Friday, November 1, 13
42

When Tdd Goes Awry

May 17, 2015

Download

Technology

Uberto Barbini

My presentation at http://www.agiletourlondon.co.uk/
Code examples at https://github.com/uberto/tdd-awry

A voyage into today Java enterprise worse practices.

Have you ever seen 10 mocks used to tests a couple of lines of code? Beans with tons of getters/setters? The same code repeated all over again with little differences? The three pasta antipattern: spaghetti, ravioli and lasagna.

From my personal experience, some examples of terrible code, written trying to follow industry best practices and TDD. Understanding the design and the goals, will help to find the way to improve it.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: When Tdd Goes Awry

When TDD Goes Awry

Clueless tests, infesting mocks and other horrors...A voyage into today Java

Enterprise worse practices.

Uberto  Barbini@ramtop

h0ps://github.com/uberto

Friday, November 1, 13

Page 2: When Tdd Goes Awry

About  me

SHOto  start

SHINHeart,  mind

In the beginner's mind there are many possibilities, in the expert's mind there are few.

My  first  program

Friday, November 1, 13

Page 3: When Tdd Goes Awry

a·wry (-r)adv.1. In a position that is turned or twisted toward one side; askew.2. Away from the correct course; amiss.

Friday, November 1, 13

Page 4: When Tdd Goes Awry

a·wry (-r)adv.1. In a position that is turned or twisted toward one side; askew.2. Away from the correct course; amiss.

     @Test     public void testGetSwapType_SPOTFWD()     {          when(mockTrade.getField(FXSubmitFields.SWAP_TYPE)).thenReturn("SPOTFWD");          setUpTrade("SWAP");          assertEquals(FXSwapType.SPOTFWD, trade.getSwapType());

          when(mockTrade.getField(FXSubmitFields.SWAP_TYPE)).thenReturn("SPOTFWD");          setUpTrade("FWDFWDSWAP");          assertEquals(FXSwapType.SPOTFWD, trade.getSwapType());     }              private void setUpTrade(final String tradingType)     {          when(mockTrade.getField(ACCOUNT)).thenReturn(ACCOUNT_VAL);          when(mockTrade.getField(CURRENCY_PAIR)).thenReturn(CURRENCY_PAIR_VAL);          when(mockTrade.getField(TRADING_TYPE)).thenReturn(tradingType);          trade = new FXTrade(mockTrade, USER, mockNearLeg, mockFarLeg);     }

Friday, November 1, 13

Page 5: When Tdd Goes Awry

Test StoriesEach test should tell a story

Scenario tests illustrate the design

Friday, November 1, 13

Page 6: When Tdd Goes Awry

Test StoriesEach test should tell a story

Scenario tests illustrate the design

When you are thinking big thoughts, write big tests. When you are thinking little thoughts, write little tests.

Kent Beck, Quora

Friday, November 1, 13

Page 7: When Tdd Goes Awry

Test StoriesEach test should tell a story

Scenario tests illustrate the design

When you are thinking big thoughts, write big tests. When you are thinking little thoughts, write little tests.

Kent Beck, Quora

Objects are nouns. Good design is a good story. Do you remember XP Metaphor?

Friday, November 1, 13

Page 8: When Tdd Goes Awry

2001

Friday, November 1, 13

Page 9: When Tdd Goes Awry

2001

My first project

Friday, November 1, 13

Page 10: When Tdd Goes Awry

2001

My first project

Meaningful test names

Friday, November 1, 13

Page 11: When Tdd Goes Awry

Test Driven DesignIt’s a kind of design technique, not a way to test.

When TDD is not useful: when your don’t care about designie. technical spikes, learning exercises

Friday, November 1, 13

Page 12: When Tdd Goes Awry

Test Driven DesignIt’s a kind of design technique, not a way to test.

When TDD is not useful: when your don’t care about designie. technical spikes, learning exercises

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence.

Kent Beck Stackoverflow

Friday, November 1, 13

Page 13: When Tdd Goes Awry

The caveman house designCarlo Pescio

Question:Why designing for testability result in good design?

Friday, November 1, 13

Page 14: When Tdd Goes Awry

The caveman house designCarlo Pescio

Question:Why designing for testability result in good design?

Global stateHidden dependenciesInflexible behavior

Things that work together are kept close

Friday, November 1, 13

Page 15: When Tdd Goes Awry

Let’s start from AssertionsOne of the least followed TTD rule says: “There must be one assertion for test”. Why?

The point behind testing one thing at time is the we want to run all the state checks, every time independently.

No IF in the tests.

No logic in the tests, much less duplication with tested logic.

Friday, November 1, 13

Page 16: When Tdd Goes Awry

Let’s start from AssertionsOne of the least followed TTD rule says: “There must be one assertion for test”. Why?

The point behind testing one thing at time is the we want to run all the state checks, every time independently.

No IF in the tests.

No logic in the tests, much less duplication with tested logic.

3 typical reasons for many assertions in a test...

Friday, November 1, 13

Page 17: When Tdd Goes Awry

Assertion Code

Friday, November 1, 13

Page 18: When Tdd Goes Awry

Mocking rulesAt most a single mock and many stubs.

Use stubs for internals and close friends, mocks for collaborators (i.e. listeners)

Stubs can be prepared in setup or with builder helpers. Mocks in the actual test.

Try to verify mocks with actual params or matcher, not any (or maybe you wanted a stub instead?).

Friday, November 1, 13

Page 19: When Tdd Goes Awry

Mock-o-meter

0 1 2 3 4 5

Friday, November 1, 13

Page 20: When Tdd Goes Awry

Mock-o-meter

0 1 2 3 4 5

If to test 3 lines of simple code, we have 10 lines of complicated test with mocks.

Which is more likely to have a bug? the code or the test?

Friday, November 1, 13

Page 21: When Tdd Goes Awry

Mocks Code

Friday, November 1, 13

Page 22: When Tdd Goes Awry

High Coupling

In software engineering, coupling or dependency is the degree to which each program module relies on each one of the other modules.antipattern of high coupling:

cohesion refers to the degree to which the elements of a module belong together.[1] Thus, it is a measure of how strongly-related each piece of functionality expressed by the source code of a software module is.

Wikipedia

Friday, November 1, 13

Page 23: When Tdd Goes Awry

A little digression: Dependency Injection frameworks

The best classes in any application are the ones that do stuff: the BarcodeDecoder, the KoopaPhysicsEngine, and theAudioStreamer. These classes have dependencies; perhaps a BarcodeCameraFinder, DefaultPhysicsEngine, and anHttpStreamer.

To contrast, the worst classes in any application are the ones that take up space without doing much at all: theBarcodeDecoderFactory, the CameraServiceLoader, and the MutableContextWrapper. These classes are the clumsy duct tape that wires the interesting stuff together.

Dagger is a replacement for these FactoryFactory classes. It allows you to focus on the interesting classes. Declare dependencies, specify how to satisfy them, and ship your app.

from Dagger introductionhttp://square.github.io/dagger/

Good things about Dagger: good and invisible duct tape

Friday, November 1, 13

Page 24: When Tdd Goes Awry

Duct Tape is important!

Friday, November 1, 13

Page 25: When Tdd Goes Awry

Duct Tape is important!

That is, it’s important to wiring up our objects in the best possible way.

Write tests to show how your wiring is done

Replace Duct Tape with Demeter

Friday, November 1, 13

Page 26: When Tdd Goes Awry

High Coupling Code

Friday, November 1, 13

Page 27: When Tdd Goes Awry

Lasagna Code

Lasagna code, coined in 1982 by Joe Celko, is a type of program structure characterized by several well-defined and separable layers, where each layer of code accesses services in the layers below through well-defined interfaces. [...] A quote usually attributed either to David Wheeler or Butler Lampson reads, "There is no problem in computer science that cannot be solved by adding another layer of indirection, except having too many layers of indirection".

Friday, November 1, 13

Page 28: When Tdd Goes Awry

Layer Code

Friday, November 1, 13

Page 29: When Tdd Goes Awry

We have a problem,

Friday, November 1, 13

Page 30: When Tdd Goes Awry

Our code is too difficult to testWe have a problem,

Friday, November 1, 13

Page 31: When Tdd Goes Awry

Our code is too difficult to testLet's write a framework to test it!

We have a problem,

Friday, November 1, 13

Page 32: When Tdd Goes Awry

Our code is too difficult to testLet's write a framework to test it!Ok, now we have 2 problems...

We have a problem,

Friday, November 1, 13

Page 33: When Tdd Goes Awry

Our code is too difficult to testLet's write a framework to test it!Ok, now we have 2 problems...

Dedicated test stub must be simple and transparent.They should explain the model, not hide it.

We have a problem,

Friday, November 1, 13

Page 34: When Tdd Goes Awry

Our code is too difficult to testLet's write a framework to test it!Ok, now we have 2 problems...

Same problem for who has to develop against a big framework: even if I have the framework tests, how can I be sure of not losing pieces around? Let's model domain simply as whole and then split it up for the framework.

Dedicated test stub must be simple and transparent.They should explain the model, not hide it.

We have a problem,

Friday, November 1, 13

Page 35: When Tdd Goes Awry

How to improve

Friday, November 1, 13

Page 36: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Friday, November 1, 13

Page 37: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Friday, November 1, 13

Page 38: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Ask to new team members or dev from other teams their impressions.

Friday, November 1, 13

Page 39: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Ask to new team members or dev from other teams their impressions.

Friday, November 1, 13

Page 40: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Ask to new team members or dev from other teams their impressions.

Experiment and share.

Friday, November 1, 13

Page 41: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Ask to new team members or dev from other teams their impressions.

Experiment and share.

Friday, November 1, 13

Page 42: When Tdd Goes Awry

How to improveIf your tests give you pain don't ignore it. Localize the cause.

Ask to new team members or dev from other teams their impressions.

Experiment and share.

Rule 0: TDD is supposed to be fun and simple.

Friday, November 1, 13