When Tdd Goes Awry

Preview:

DESCRIPTION

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.

Citation preview

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

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

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

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

Test StoriesEach test should tell a story

Scenario tests illustrate the design

Friday, November 1, 13

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

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

2001

Friday, November 1, 13

2001

My first project

Friday, November 1, 13

2001

My first project

Meaningful test names

Friday, November 1, 13

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

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

The caveman house designCarlo Pescio

Question:Why designing for testability result in good design?

Friday, November 1, 13

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

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

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

Assertion Code

Friday, November 1, 13

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

Mock-o-meter

0 1 2 3 4 5

Friday, November 1, 13

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

Mocks Code

Friday, November 1, 13

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

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

Duct Tape is important!

Friday, November 1, 13

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

High Coupling Code

Friday, November 1, 13

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

Layer Code

Friday, November 1, 13

We have a problem,

Friday, November 1, 13

Our code is too difficult to testWe have a problem,

Friday, November 1, 13

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

We have a problem,

Friday, November 1, 13

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

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

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

How to improve

Friday, November 1, 13

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

Friday, November 1, 13

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

Friday, November 1, 13

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

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

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

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

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

Recommended