36
TDD in Practice Alan Christensen @christensena

TDD In Practice

Embed Size (px)

DESCRIPTION

Talk I gave at Christchurch Code Camp, August 2013 on test driven development

Citation preview

Page 1: TDD In Practice

TDD in Practice

Alan Christensen @christensena

Page 2: TDD In Practice

Preamble

•Who am I?

•My TDD journey

Page 3: TDD In Practice

Overview

•TDD to drive out design (live coding)

•Two approaches to TDD

•Bit on architecture and design

Page 4: TDD In Practice

TDD for Design

•TDD is supposed to improve your design

•How does that work?

Page 5: TDD In Practice

Worked example

•Order confirmation (think shopping cart)

•Payment has already been taken

•What next?

Page 6: TDD In Practice

Order Confirmation

•Flag order as Ready to Ship

•Notify customer, e.g. confirmation email

•Arrange shipment

Page 7: TDD In Practice

coding time!

Page 8: TDD In Practice

OrderConfirmationEmailBuilderOrderConfirmer

Test Test

OrderConfirmationEmailBuilder

Fake

Email TemplateEngine

Fake

Page 9: TDD In Practice

Review•Try to keep the Red Green Refactor

discipline

•NCrunch is wonderful but costs $$$

•Use test naming to document behaviour

•Asserts should match test naming (so typically one assert per test)

•Arrange/Act/Assert helps with readability

Page 10: TDD In Practice

Review: Mocking

•Prefer state based tests

•Prefer manual (static) fakes over dynamic

•Prefer stubs if using dynamic mocks

•Use adapters over untestable code

•Use adapters/facades to make application code more expressive of intent

Page 11: TDD In Practice

Review: TDD Design

•Starting with test helps focus on good API

•When test setups (Arrange) get large, it usually tells us we need to factor code into smaller pieces (classes, modules whatever)

•Tests help us focus on one small component at a time

•Often end up with more general, re-usable components (with rigorous tests)

Page 12: TDD In Practice

Lots of tiny classes!

•Is this a bad thing?

•Best use a DI container

•used right they fade into the background

•Use IDE code navigation tools

•e.g. Go to Definition, Find Usages, Ctrl-T in R#

•Use keyboard shortcuts

Page 13: TDD In Practice

Disadvantages

•Any problems with this approach?

Page 14: TDD In Practice

Two TDD approaches

•“Unit testing is out, vertical slice testing is in” - Sebastian Lambla (2013)

Page 15: TDD In Practice

Two TDD Approaches

“A lot of the bad advice about TDD has come from believing that it means testing a module in isolation from other modules, so that you essentially can only have one class under test and you have to have everything else mocked out.” - Ian Cooper (NDC in Oslo 2013 TDD: where did it all go wrong?)

Page 16: TDD In Practice

OrderConfirmationEmailBuilderOrderConfirmer

Test Test

OrderConfirmationEmailBuilder

Fake

Mail TemplateEngine

Fake

Page 17: TDD In Practice

What is a unit test?

•All about isolation, but from what?

•Other classes or methods?

•Other systems (e.g. file system, email, database)?

•Other tests?

Page 18: TDD In Practice

Isolation approach

•Focused test suites, specify behaviour of small units (e.g. classes)

•Substitute out all dependencies

•Tests inevitably specify implementation details to some extent

Page 19: TDD In Practice

OrderConfirmationEmailBuilderOrderConfirmer

Test Test

OrderConfirmationEmailBuilder

Fake

Mail Template Engine

Fake

Page 20: TDD In Practice

isolated: the good

•Focused tests allow us to focus on one thing at a time

•When tests fail, the source of problem is usually easy to identify

•Set ups are small, tests always fast

•Encourages well-factored code

•Tests relatively easy to write

Page 21: TDD In Practice

isolated: the bad

•Tends to lock in to a specific implementation

•Tests can become a liability, slowing down refactoring

•Can lead to focus on implementation details over business value

Page 22: TDD In Practice

vertical slice approach

•Tests talk to public API only

•Tests verify expected results, but not how they are arrived at

• Isolation is between tests, not between “units”.

•Test suite per feature instead of per class

•Still don’t touch external systems (i.e. still fast and stable)

Page 23: TDD In Practice

MailSenderOrderConfirmer

Test

Page 24: TDD In Practice

MailSenderOrderConfirmation

EmailBuilderOrderConfirmer

Test

Email TemplatingEngine

Page 25: TDD In Practice

vertical slices: the good

•More expressive tests

•More able to change implementation without breaking tests

Page 26: TDD In Practice

vertical slices: the bad

•Harder to drive out your design

•Easy to “get lost” in the implementation without close guidance of your tests

•Harder to pinpoint bugs when tests fail

•Can be more difficult to write tests

Page 27: TDD In Practice

http://www.woodwrightschool.com/ship-in-a-bottle-w-jim/http://www.woodwrightschool.com/ship-in-a-bottle-w-jim/

Page 28: TDD In Practice

So which to use?

•The answer of course: it depends...

•Isolation when “discovering” your design

•Replace them as appropriate with vertical slice tests

•Delete brittle tests! Use code coverage tools to ensure you still have coverage

Page 29: TDD In Practice
Page 30: TDD In Practice

Other tips

•Use “builder” pattern for making test data

•Refactor test code like “real” code. Keep it clean!

•There is no “right” way to do things

Page 31: TDD In Practice

Traditional architecture

UI

Services

DB

Page 32: TDD In Practice

Hexagonal Architecture

http://matteo.vaccari.name/blog/archives/154

Page 33: TDD In Practice

Hexagonal Architecture - Alastair Cockburn

Page 34: TDD In Practice

Links

• Source code and link to these slides including this one! https://github.com/christensena/TDDIntro

• TDD, where did it all go wrong? (Ian Cooper, NDC 2013) http://vimeo.com/68375232

• http://codebetter.com/sebastienlambla/2013/07/11/unit-testing-is-out-vertical-slice-testing-is-in/

• http://martinfowler.com/articles/mocksArentStubs.html

• http://alistair.cockburn.us/Hexagonal+architecture

Page 35: TDD In Practice

Questions?

Page 36: TDD In Practice

Reruns

•Repeating this talk 29 August at Christchurch APN

Alan Christensen @christensena