Software Engineering and Architecture Test Stubs and Doubles - - PowerPoint PPT Presentation

software engineering
SMART_READER_LITE
LIVE PREVIEW

Software Engineering and Architecture Test Stubs and Doubles - - PowerPoint PPT Presentation

Software Engineering and Architecture Test Stubs and Doubles getting the world under test control GammaTowns RateStrategy But how to test? How do I TDD it? Read system clock to etc. etc. determine if weekend CS, AU Henrik Brbak


slide-1
SLIDE 1

Software Engineering and Architecture

Test Stubs and Doubles … getting the world under test control

slide-2
SLIDE 2

GammaTown’s RateStrategy

CS, AU Henrik Bærbak Christensen 2

Read system clock to determine if weekend

But how to test? How do I TDD it?

  • etc. etc.
slide-3
SLIDE 3

Tricky Requirement

  • The test case for AlphaTown:
  • … problematic for GammaTown…

Henrik Bærbak Christensen 3 CS, AU

slide-4
SLIDE 4

Analysis

  • Gammatown, however, has one more parameter in the

rate policy test case

  • The problem is

This parameter is not accessible from the testing code!

Henrik Bærbak Christensen 4 CS, AU

slide-5
SLIDE 5

Code view

CS, AU Henrik Bærbak Christensen 5

Direct input parameter: payment Indirect input parameter: day of week

???

slide-6
SLIDE 6

TDD of State Pattern

  • To implement GammaTown requirements I do it manually

CS, AU Henrik Bærbak Christensen 6

slide-7
SLIDE 7

But it is bad …

  • After introducing Gammatown I no longer have

automated tests because I have to run some of the tests during the weekend.

– I have a ‘manual run on weekend and another run on weekdays targets’

  • I want to get back to as much automated testing as

possible.

Henrik Bærbak Christensen 7 CS, AU

slide-8
SLIDE 8

Analysis of Parameters

CS, AU Henrik Bærbak Christensen 8

Direct input parameter: payment Indirect input parameter: day of week

???

slide-9
SLIDE 9

Definitions

  • This reflection allows me to classify parameters:
  • UUT = Unit Under Test.

– here it is the AlternatingRateStrategy instance...

Henrik Bærbak Christensen 9 CS, AU

slide-10
SLIDE 10

Where does indirect input come from?

  • So the 1000$ question is: where does the indirect input

parameter come from?

  • Exercise: Name other types of indirect input?

Henrik Bærbak Christensen 10 CS, AU

slide-11
SLIDE 11

Analysis: Code view

  • Structure of xUnit test cases

– Collaboration diagram: interaction between objects

  • DOU = Depended On Unit

Henrik Bærbak Christensen 11 CS, AU

slide-12
SLIDE 12

Direct versus Indirect

Henrik Bærbak Christensen 12

Direct input Indirect input

CS, AU

slide-13
SLIDE 13

The Gammatown Rate Policy

  • My DOU is the Java system clock:

Henrik Bærbak Christensen 13

Test code AlternatingRateStrategy System Clock System.DateTime java.util.Calendar Method parameters Calling library methods

CS, AU

slide-14
SLIDE 14

The Challenge

  • This analysis allows me to state the challenge:
  • How can I make the DOU return values that are defined

by the testing code?

Henrik Bærbak Christensen 14

Test code AlternatingRateStrategy System Clock System.DateTime java.util.Calendar

CS, AU

slide-15
SLIDE 15

Analysis

  • Basically it is a variability problem

– During testing, use data given by test code – During normal ops, use data given by system

  • So I can reuse my previous analysis

– parametric proposal – polymorphic proposal – compositional proposal

Henrik Bærbak Christensen 15 CS, AU

Scientists like to do this all the time! If we can rephrase a new question into an

  • ld one, whose answer is known – then

we are done ☺

slide-16
SLIDE 16

Parametric

  • This is perhaps the oldest solution in the C world
  • #ifdef DEBUG
  • today = PRESET_VALUE;
  • #else
  • today = (get date from clock);
  • #
  • return today == Saturday || today == Sunday;

Henrik Bærbak Christensen 16 CS, AU

slide-17
SLIDE 17

Polymorphic

  • Subclass or die...
  • Actually a quite reasonable approach...
  • Argue why!!!

Henrik Bærbak Christensen 17

AlternatingRateStrategy TestAlternatingRateStrategy

CS, AU

Override ‘isWeekend()’ method

slide-18
SLIDE 18

Compositional

  • 3-1-2 leads to yet another Strategy Pattern:

Henrik Bærbak Christensen 18 CS, AU

slide-19
SLIDE 19

Static Architecture View

  • Exercise: Why is this Strategy and not State?

Henrik Bærbak Christensen 19 CS, AU

slide-20
SLIDE 20

Production Code

CS, AU Henrik Bærbak Christensen 20

slide-21
SLIDE 21

The Stub

CS, AU Henrik Bærbak Christensen 21

slide-22
SLIDE 22

Test Code

CS@AU Henrik Bærbak Christensen 22

slide-23
SLIDE 23

Rephrasing as Test Case

CS, AU Henrik Bærbak Christensen 23

Direct input parameter: payment Now: Direct input parameter: weekend or not

slide-24
SLIDE 24

Sorry Bob 

  • I had not read Uncle Bob when I wrote the book

– What property is the present code missing?

CS@AU Henrik Bærbak Christensen 24

slide-25
SLIDE 25

Today I would…

  • … introduce an Enum type

– No flag argument, replaced by descriptive names

CS@AU Henrik Bærbak Christensen 25

IS_WEEKDAY IS_WEEKEND

slide-26
SLIDE 26

Test Stub

  • I have made a test stub

Henrik Bærbak Christensen 26 CS, AU

slide-27
SLIDE 27

Key point

  • The use of Test doubles is a key technique in modern

agile development !!!

CS, AU Henrik Bærbak Christensen 27

slide-28
SLIDE 28

Note

  • Please note that once again the 3-1-2 is the underlying

and powerful engine for Test Stub.

  • I use the 3-1-2 to derive a solution that “accidentally” has

a name and is a well known concept; just as I previously derived several design patterns.

Henrik Bærbak Christensen 28 CS, AU

slide-29
SLIDE 29

Reusing the variability points...

Aah – I could do this...

CS, AU Henrik Bærbak Christensen 29

slide-30
SLIDE 30

Variability points to the rescue

  • The WeekendDecisionStrategy introduces yet another

variability point...

  • Often they come in handy later if

– 1) they encapsulate well-defined responsibilities – 2) are defined by interfaces and – 3) uses delegation ☺

CS, AU Henrik Bærbak Christensen 30

slide-31
SLIDE 31

Static Architecture View

Henrik Bærbak Christensen 31 CS, AU

slide-32
SLIDE 32

Manual testing

  • Manual testing of GammaTown, for demo to end users!

CS, AU Henrik Bærbak Christensen 32

slide-33
SLIDE 33

Discussion

CS, AU Henrik Bærbak Christensen 33

slide-34
SLIDE 34

Test Doubles

  • Test Stub is a subtype of Test Double. Other sub types

exists:

– Stub: Get indirect input under control – Spy: Get indirect output under control

  • to validate that UUT use the proper protocol

– count method calls, ensure proper call sequence, validate set values,

– Mock: A spy with fail fast property

  • Frameworks exists that test code can ‘program’ mocks without every

coding them in the native language

  • Fail fast: fail on first breaking of protocol

– Fake: A lightweight but realistic double

  • when the UUT-DOU interaction is slow and tedious
  • when the Double interaction is not the purpose of test

Henrik Bærbak Christensen 34 CS, AU

Return to it shortly Source: http://xunitpatterns.com/, G. Meszaros

slide-35
SLIDE 35

Package/Namespace View

  • Gradle dictate that we split the code into two trees

– src/main/java: all production code rooted here – src/test/java: all test code rooted here

  • Here

– WeekendDecisionStrategy (interface) – ClockBasedDecisionStrategy (class) – FixedDecisionStrategy (class)

  • Exercise: Where would you put these units?

Henrik Bærbak Christensen 35 CS, AU

slide-36
SLIDE 36

C# Delegates / Java 8 Lambda

  • The strategy only contains a single method and having

an interface may seem a bit of an overkill.

– In Java 8, you can use a Lambda – In C# you may use delegates that is more or less a type safe function pointer. – In functional languages you may use closures

Henrik Bærbak Christensen 36 CS, AU

slide-37
SLIDE 37

Test Spy

Missing in the FRS book But – they are in the exam set…

slide-38
SLIDE 38

Direct versus Indirect

  • But – there is also output from UUTs

Henrik Bærbak Christensen 38

Direct input Indirect input

CS, AU

Direct output Indirect output

slide-39
SLIDE 39

Example

  • UUT: Algorithm to turn on heating in home, based upon

measuring the room’s temperature

– if (sensor.measureTemperature() < 20) heater.turnOn();

  • Test case in JUnit

– Given a HeatingController – When the temperature falls to 19 degrees – Then the heater should be turned on

CS@AU Henrik Bærbak Christensen 39

slide-40
SLIDE 40

Code View

CS@AU Henrik Bærbak Christensen 40

Issue: I must validate that ‘turnOn()’ is called by our UUT = HeatingController. But how? It is indirect output from UUT

slide-41
SLIDE 41

Exercise: Spend 2 minutes

CS@AU Henrik Bærbak Christensen 41

Issue: I must validate that ‘turnOn()’ is called by our UUT = HeatingController. But how? It is indirect output from UUT

slide-42
SLIDE 42

Solution

  • Is a Test Spy

– A ‘recorder’ which records the indirect output sent out by the UUT

  • … whose recorded values

can be asserted…

CS@AU Henrik Bærbak Christensen 42

slide-43
SLIDE 43

Solution

  • Spies often need to have specialized retrieval interfaces

– i.e. methods that are not in the normal interface, only in the implementing Spy class

  • To get access to the recorded values
  • So you have to instantiate the spy by the class, not by the

interface type…

– Now ‘isTurnedOn()’ is accessible…

CS@AU Henrik Bærbak Christensen 43

slide-44
SLIDE 44

Summary

slide-45
SLIDE 45

Key Points

  • Test Stubs (Doubles) make software testable.
  • 3-1-2 technique help isolating DOUs

– because I isolated the responsibility by an interface I had the

  • pportunity to delegate to a test stub
  • My solution is overly complex

– Yes! Perhaps subclassing in test tree would be better here ☺ – But

  • it scales well to complex DOUs
  • it is good at handling aspects that may vary across the entire system

(see next slide)

Henrik Bærbak Christensen 45 CS, AU

slide-46
SLIDE 46

This is a PowerTool

  • Test Doubles usage are a key technique in modern,

microservice, continuous deployment, development!!!

– Build servers that automatically pull git repositories for newest releases, runs extensive tests, and finally pushes code into production on the production servers…

  • It would not be possible if stubs, spies, fake objects,

mocks were not used to thoroughly test using automated testing!

  • Example:

– NetFlix need to survive server crashes to continue streaming

  • Test stubs (‘saboteurs’) throw IOExceptions to simulate failures…

CS@AU Henrik Bærbak Christensen 46

slide-47
SLIDE 47

Still Untested Code

  • Some code units are not automatically testable in a cost-

efficient manner

– Note that if I rely on the automatic tests only, then the ClockBasedDecisionStrategy instance is never tested!

  • (which it actually was when using the manual tests!)
  • Thus:

– DOUs handling external resources must still be manually tested (and/or formally reviewed by software reviews). – Keep ‘non-testable code’ in the smallest possible software unit, and if it ain’t broke, then don’t fix it ☺

Henrik Bærbak Christensen 47 CS, AU

slide-48
SLIDE 48

Know When to Stop Testing

  • Note also that I do not test that the return values from the

system library methods are not tested.

  • I expect Oracle / MicroSoft to test their software.

– sometimes we are wrong but it is not cost efficient.

  • Do not test the random generator ☺

Henrik Bærbak Christensen 48 CS, AU