unit testing - the hard parts

73
Shaun Abram Blog: shaunabram.com Email: [email protected] Twitter: @shaunabram LinkedIn: linkedin.com/in/sabram Unit Testing The hard parts October 10 th , 2015

Upload: shaun-abram

Post on 16-Feb-2017

817 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Unit testing - the hard parts

Shaun AbramBlog: shaunabram.comEmail: [email protected]: @shaunabramLinkedIn: linkedin.com/in/sabram

Unit TestingThe hard parts

October 10th, 2015

Page 2: Unit testing - the hard parts

Shaun Abram 2

Test Obsessed?

How much do you know…Test coverageDependency InjectionMock vs stubsTesting private or static methodsTest driven development

Page 3: Unit testing - the hard parts

Shaun Abram 3

What is a unit test?

A piece of code that executes a specific functionality (‘unit’) in the code, andConfirms behavior or result is as expected

Determines if code is ‘fit for use’Does it do what the developer intended?

Before, we manually verified, but not easily repeatable.

Page 4: Unit testing - the hard parts

Shaun Abram 4

Why unit test?

Economics $but also…

Drive design Create defensive code against bad input

Act as safety buffers for regression bugs

Provide documentationClean codeLess bugs

Page 5: Unit testing - the hard parts

Shaun Abram 5

What is a unit?

A class? A method? A single path through a method?

The smallest testable part of an application. A single functional use case.

Page 6: Unit testing - the hard parts

Shaun Abram 6

What makes a good unit test?Provides benefit!Readable, Understandable, Maintainable

Independent run in any order, no DB or File access

Consistent / deterministicRuns fastTests a single logical concept in the system

Page 7: Unit testing - the hard parts

Shaun Abram 7

Unit testing limitations

Can not prove the absence of bugs

Lot’s of code (x3-5)

Some things difficult to test

Page 8: Unit testing - the hard parts

Shaun Abram 8

Dependency Injection

Page 9: Unit testing - the hard parts

9

Page 10: Unit testing - the hard parts

10

Dependency Injection Useful for testing – inject test doubles Also helps reduce coupling

Page 11: Unit testing - the hard parts

Shaun Abram 11

Test Doubles

MocksStubs

DummiesSpies

Fakes

Page 12: Unit testing - the hard parts

Shaun Abram 12

Test Doubles

MocksStubs

DummiesSpies

Fakes

Page 13: Unit testing - the hard parts

Shaun Abram 13

Test Doubles: Mocks

Mocks: An overloaded term!

uses behavior verificationobjects pre-programmed with expectations

Page 14: Unit testing - the hard parts

14

Page 15: Unit testing - the hard parts

15

Mocks use behavior verification Can specify how to respond when called Roll your own?

Page 16: Unit testing - the hard parts

Shaun Abram 16

Test Doubles

MocksStubs

DummiesSpies

Fakes

Page 17: Unit testing - the hard parts

Shaun Abram 17

Test Doubles: Stubs

‘stubs out’or provides a simplified version

of the implementation for the purposes of testing

Page 18: Unit testing - the hard parts

18

Page 19: Unit testing - the hard parts

19

Stubs can use state or behavior verification Provides a useful approach for test fixture configurability

Page 20: Unit testing - the hard parts

Shaun Abram 20

Test Doubles

MocksStubs

DummiesSpies

Fakes

Page 21: Unit testing - the hard parts

Shaun Abram 21

Test Doubles: DummiesA very dumb class! Contains next to nothing - enough to compile

Pass when you don’t expect to be used

Page 22: Unit testing - the hard parts

22

Use dummies with state or behavior verification Can create as inner class Can replicate with mocks

Page 23: Unit testing - the hard parts

Shaun Abram 23

Unit Testing – the tricky partsLegacy codePrivates Statics

Page 24: Unit testing - the hard parts

Shaun Abram 24

General approach to testing legacy code

1) Start with coarse grained testsNo modificationsStrict and rigidDetect regressionsShort term bridges - delete

Page 25: Unit testing - the hard parts

Shaun Abram 25

General approach to testing legacy code

1) Start with coarse grained tests2) Add finer grained tests Incrementally add more unit start gently refactoring Use TDD – if possibleTest from 1) should protect you

Page 26: Unit testing - the hard parts

Shaun Abram 26

General approach to testing legacy code

1) Start with coarse grained tests2) Add finer grained tests3) Continuously refactorUse patterns such as Extract Method/ClassMove Method/Fieldtease apart methods (>10 lines smells)

Page 27: Unit testing - the hard parts

Shaun Abram 27

Unit Testing – the tricky partsLegacy codePrivates Statics

Page 28: Unit testing - the hard parts

Shaun Abram 28

How do you test private methods?

Indirectly! Best tested via public interface

But sometimes…Legacy code

With limited capability to refactor, or

adding a safety net before refactoring

A public method calls several private methods, each with complex logic

Page 29: Unit testing - the hard parts

Shaun Abram 29

Testing Private Methods

1. Refactor2. Change the visibility

Bad practicePublic API? Very bad practice! Internal & stepping stone -> lesser evil

Java private -> package; .Net protected or internal?

Document (@VisibleForTesting)

Page 30: Unit testing - the hard parts

Shaun Abram 30

Testing Private Methods

1. Refactor2. Change the visibility3. Use ReflectionNo code modification, but…4. Other options…

Testing frameworks InternalsVisibleToAttributePrivate Accessors

Page 31: Unit testing - the hard parts

Shaun Abram 31

Testing static methods

Page 32: Unit testing - the hard parts

32

Page 33: Unit testing - the hard parts

33

Page 34: Unit testing - the hard parts

34

Page 35: Unit testing - the hard parts

Shaun Abram 35

Testing static methodsDI idealBut sometimes not pragmatic

Page 36: Unit testing - the hard parts

36

Page 37: Unit testing - the hard parts

37

Refactor to wrap the static call in an instance methodWhich can then be mocked…

Page 38: Unit testing - the hard parts

38

Page 39: Unit testing - the hard parts

39

Page 40: Unit testing - the hard parts

40

Page 41: Unit testing - the hard parts

Shaun Abram 41

Testing static methodsRefactor – use DIWrap static call in a instance methodUse a mocking framework?

Page 42: Unit testing - the hard parts

Shaun Abram 42

Test Driven Development

Page 43: Unit testing - the hard parts

Shaun Abram 43

Test Driven Development

Page 44: Unit testing - the hard parts

Shaun Abram 44

Test Driven Development

Page 45: Unit testing - the hard parts

Shaun Abram 45

Test Driven Development

Page 46: Unit testing - the hard parts

Shaun Abram 46

Test Driven Development

Page 47: Unit testing - the hard parts

Shaun Abram 47

Test Driven Development

Red - Green – Refactor: the TDD MantraNo new functionality without a failing test

No refactoring without passing tests

Page 48: Unit testing - the hard parts

Shaun Abram 48

Test Driven Development Example…

Page 49: Unit testing - the hard parts

Shaun Abram 49

Test Driven Development Example…

Create a StringCalculator class with an add method which takes a comma separate String of numbers and returns their sum.

Example input Result0

1 1

2 2

1,2 3

1,2,100 103

Page 50: Unit testing - the hard parts

50

Page 51: Unit testing - the hard parts
Page 52: Unit testing - the hard parts
Page 53: Unit testing - the hard parts
Page 54: Unit testing - the hard parts
Page 55: Unit testing - the hard parts
Page 56: Unit testing - the hard parts

Refactor?

Page 57: Unit testing - the hard parts
Page 58: Unit testing - the hard parts
Page 59: Unit testing - the hard parts
Page 60: Unit testing - the hard parts
Page 61: Unit testing - the hard parts

Refactor?

Page 62: Unit testing - the hard parts
Page 63: Unit testing - the hard parts
Page 64: Unit testing - the hard parts
Page 65: Unit testing - the hard parts
Page 66: Unit testing - the hard parts
Page 67: Unit testing - the hard parts
Page 68: Unit testing - the hard parts
Page 69: Unit testing - the hard parts
Page 70: Unit testing - the hard parts

These tests act like the original developer looking over your shoulder and advising you, long after that developer has left…

These tests act like the original developer looking over your shoulder and advising you, long after that developer has left…

Page 71: Unit testing - the hard parts

Shaun Abram 71

Recommended reading

Growing Object-Oriented Software, Guided by TestsFreeman & Pryce

Test Driven DevelopmentKent Beck

Refactoring: Improving the Design of Existing CodeMartin Fowler, Kent Beck et. al.

Effective Unit TestingLasse Koskela

Page 73: Unit testing - the hard parts

Questions?