TDD - test doubles

21
Test Doubles @AlfredoCasado

description

Slides for a little introduction to test doubles given at the madrid software craftsmanship group.

Transcript of TDD - test doubles

Page 1: TDD - test doubles

Test Doubles @AlfredoCasado

Page 2: TDD - test doubles

Object oriented system

storage

messaging

Page 3: TDD - test doubles

Object oriented system

storage

messaging

Page 4: TDD - test doubles

Object oriented system

storage

messaging

Page 5: TDD - test doubles

Object oriented system

storage

messaging

Page 6: TDD - test doubles

Object oriented system

storage

messaging

Page 7: TDD - test doubles

Object oriented system

storage

messaging

Page 8: TDD - test doubles

Problem: test only a selected subset of elements

storage

messaging

Page 9: TDD - test doubles

Solution: use test doubles to isolate

Page 10: TDD - test doubles

STUBS● Use stubs to simulate inputs to your system

under test.● In BDD terminology, stubs helps in the given

part of the test.

Page 11: TDD - test doubles

Example: calculating a student's grade point average

averageGrade(student)stub

grades(student)

OOP: 8,Algorithms: 6,FP: 6,Databases: 10

7,5

Page 12: TDD - test doubles

Code example (groovy with spock)

def "calculate average grade"() { given: def stub = Mock(GradesRepository) { grades('alfredo') >> [OOP: 8,algorithms: 6,FP: 6,databases: 10] }

def gradesEvaluator = new GradesEvaluator(gradesRepository: stub)

expect: gradesEvaluator.averageGrade('alfredo') == 7.5

}

stub creation

Page 13: TDD - test doubles

Code example (groovy with spock)

def "calculate average grade"() { given: def stub = Mock(GradesRepository) { grades('alfredo') >> [OOP: 8,algorithms: 6,FP: 6,databases: 10] }

def gradesEvaluator = new GradesEvaluator(gradesRepository: stub)

expect: gradesEvaluator.averageGrade('alfredo') == 7.5

}

stub injection

Page 14: TDD - test doubles

Mocks/Spies● Use mocks/Spies to verify outputs of your system under

test.● In BDD terminology, mocks/spies helps in the then part

of the test.● With mocks you set expectations before call the SUT,

this are usually “strict” expectations and no other interactions with the double are allowed.

● With spies you check the interactions with the double after call the SUT.

Page 15: TDD - test doubles

Example: Domotic system

activateSecurity()

WindowsMockclose()

close() DoorsMock

output you want to verify

Page 16: TDD - test doubles

Code example with mocks (java & jmock)

@Test public void test_activate_security() { final WindowController windowMock = context.mock(WindowController.class); final DoorsController doorsMock = context.mock(DoorsController.class); context.checking(new Expectations() {{ oneOf(windowMock).close(); oneOf(doorsMock).close(); }}); DomoticSystem domotic = new DomoticSystem(windowMock, doorsMock); domotic.activateSecurity(); context.assertIsSatisfied(); }

mocks creation

Page 17: TDD - test doubles

@Test public void test_activate_security() { final WindowController windowMock = context.mock(WindowController.class); final DoorsController doorsMock = context.mock(DoorsController.class); context.checking(new Expectations() {{ oneOf(windowMock).close(); oneOf(doorsMock).close(); }}); DomoticSystem domotic = new DomoticSystem(windowMock, doorsMock); domotic.activateSecurity(); context.assertIsSatisfied(); }

Code example with mocks (java & jmock)

set expectations

Page 18: TDD - test doubles

@Test public void test_activate_security() { final WindowController windowMock = context.mock(WindowController.class); final DoorsController doorsMock = context.mock(DoorsController.class); context.checking(new Expectations() {{ oneOf(windowMock).close(); oneOf(doorsMock).close(); }}); DomoticSystem domotic = new DomoticSystem(windowMock, doorsMock); domotic.activateSecurity(); context.assertIsSatisfied(); }

Code example with mocks (java & jmock)

verify interactions

Page 19: TDD - test doubles

@Test public void test_activate_security() { WindowController windowSpy = mock(WindowController.class); DoorsController doorsSpy = mock(DoorsController.class); DomoticSystem domotic = new DomoticSystem(windowSpy, doorsSpy); domotic.activateSecurity(); verify(windowSpy).close(); verify(doorsSpy).close(); }

Code example with spies (java & mockito)

spy creation

Page 20: TDD - test doubles

Code example with spies (java & mockito)

@Test public void test_activate_security() { WindowController windowSpy = mock(WindowController.class); DoorsController doorsSpy = mock(DoorsController.class); DomoticSystem domotic = new DomoticSystem(windowSpy, doorsSpy); domotic.activateSecurity(); verify(windowSpy).close(); verify(doorsSpy).close(); }

verify interactions

Page 21: TDD - test doubles

Recommendations● Test features not methods or classes● Kent Beck definition of unit test is a test that

can run in isolation from other test. A unit test is not test a class in isolation.

● Don’t use test doubles for Value Objects● Don’t use test doubles for types you don’t

own