Slide 1

Slide 1 text

Copyright © 2014 Russel Winder 1 Spocktacular Testing Russel Winder email: [email protected] xmpp: [email protected] twitter: @russel_winder Web: http://www.russel.org.uk

Slide 2

Slide 2 text

Copyright © 2014 Russel Winder 2 Opening

Slide 3

Slide 3 text

Copyright © 2014 Russel Winder 3

Slide 4

Slide 4 text

Copyright © 2014 Russel Winder 4 An Historical Perspective

Slide 5

Slide 5 text

Copyright © 2014 Russel Winder 5 Spock sUnit TestNG JUnit GroovyTestCase jBehave RSpec JUnit4 BDD TDD

Slide 6

Slide 6 text

Copyright © 2014 Russel Winder 6 Spock is Groovy-based… …but can test any JVM-based code.

Slide 7

Slide 7 text

Copyright © 2014 Russel Winder 7 NB Testing frameworks support integration and system testing as well as unit testing.

Slide 8

Slide 8 text

Copyright © 2014 Russel Winder 8

Slide 9

Slide 9 text

Copyright © 2014 Russel Winder 9 Testing ● Unit: ● Test the classes, functions and methods to ensure they do what we need them to. ● As lightweight and fast as possible. ● Run all tests always. ● Integration and system: ● Test combinations or the whole thing to make sure the functionality is as required. ● Separate process to create a sandbox . “ ” ● If cannot run all tests always, create smoke tests.

Slide 10

Slide 10 text

Copyright © 2014 Russel Winder 10 Code Under Test static message() { 'Hello World.' } println message() helloWorld.groovy

Slide 11

Slide 11 text

Copyright © 2014 Russel Winder 11 Unit Test @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import helloWorld class Test_HelloWorld extends Specification { def 'ensure the message function returns hello world'() { expect: helloWorld.message() == 'Hello World.' } }

Slide 12

Slide 12 text

Copyright © 2014 Russel Winder 12 System Test @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification class Test_HelloWorld extends Specification { def 'executing the script results in hello world on the standard output'() { given: def process = 'helloWorld.groovy'.execute() expect: process.waitFor() == 0 process.in.text == 'Hello World.\n' } }

Slide 13

Slide 13 text

Copyright © 2014 Russel Winder 13 A bit less Groovy…

Slide 14

Slide 14 text

Copyright © 2014 Russel Winder 14 Code under Test package uk.org.winder.spockworkshop; class HelloWorld { private static String message() { return "Hello World."; } public static void main(final String[] args) { System.out.println(message()); } } HelloWorld.java

Slide 15

Slide 15 text

Copyright © 2014 Russel Winder 15 Unit Test package uk.org.winder.spockworkshop import spock.lang.Specification class Test_HelloWorld extends Specification { def 'ensure the message function returns hello world'() { expect: HelloWorld.message() == 'Hello World.' } }

Slide 16

Slide 16 text

Copyright © 2014 Russel Winder 16 Project Structure . ├── build.gradle └── src ├── main │ └── java │ └── uk │ └── org │ └── winder │ └── spockworkshop │ └─- HelloWorld.java └── test └── groovy └── uk └── org └── winder └── spockworkshop └── unitTest_helloWorld.groovy

Slide 17

Slide 17 text

Copyright © 2014 Russel Winder 17 Build Gradle — apply plugin: 'groovy' apply plugin: 'application' repositories { mavenCentral() } dependencies { testCompile 'org.spockframework:spock-core:0.7-groovy-2.0' } mainClassName = 'uk.org.winder.spockworkshop.HelloWorld'

Slide 18

Slide 18 text

Copyright © 2014 Russel Winder 18

Slide 19

Slide 19 text

Copyright © 2014 Russel Winder 19 Moving On

Slide 20

Slide 20 text

Copyright © 2014 Russel Winder 20

Slide 21

Slide 21 text

Copyright © 2014 Russel Winder 21 Spock Test Structure

Slide 22

Slide 22 text

Copyright © 2014 Russel Winder 22 given:

Slide 23

Slide 23 text

Copyright © 2014 Russel Winder 23 Code Under Test static message() { 'Hello World.' } println message() helloWorld.groovy

Slide 24

Slide 24 text

Copyright © 2014 Russel Winder 24 Unit Test @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import helloWorld class Test_HelloWorld extends Specification { def 'ensure the message function returns hello world'() { expect: helloWorld.message() == 'Hello World.' } }

Slide 25

Slide 25 text

Copyright © 2014 Russel Winder 25 Another Code Under Test class Stuff { private final data = [] def leftShift(datum) { data << datum } } Stuff.groovy

Slide 26

Slide 26 text

Copyright © 2014 Russel Winder 26 Unit Testing It @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import Stuff class TestStuff extends Specification { def 'check stuff'() { given: def stuff = new Stuff() expect: stuff.data == [] when: stuff << 6 then: stuff.data == [6] when: stuff << 6 then: stuff.data == [6, 6] } def 'check other stuff'() { given: def stuff = new Stuff() expect: stuff.data == [] when: stuff.leftShift(6) then: stuff.data == [6] when: stuff.leftShift(6) then: stuff.data == [6, 6] } }

Slide 27

Slide 27 text

Copyright © 2014 Russel Winder 27

Slide 28

Slide 28 text

Copyright © 2014 Russel Winder 28 Data-driven Testing

Slide 29

Slide 29 text

Copyright © 2014 Russel Winder 29

Slide 30

Slide 30 text

Copyright © 2014 Russel Winder 30 given:

Slide 31

Slide 31 text

Copyright © 2014 Russel Winder 31 Code Under Test Id.groovy class Id { def eval(x) { x } }

Slide 32

Slide 32 text

Copyright © 2014 Russel Winder 32 Unit Test Code #! /usr/bin/env groovy @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import spock.lang.Unroll class idTest extends Specification { @Unroll def 'the id eval function always return the value of the parameter'() { given: final id = new Id () expect: id.eval(i) == i where: i << [0, 1, 2, 3, 's', 'ffff', 2.05] } }

Slide 33

Slide 33 text

Copyright © 2014 Russel Winder 33 Code Under Test class Functions { static square(x) { x * x } } Functions.groovy

Slide 34

Slide 34 text

Copyright © 2014 Russel Winder 34 Unit Test Variant 1 — #! /usr/bin/env groovy @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import spock.lang.Unroll class functionsTest_alt_1 extends Specification { @Unroll def 'square always returns the square of the numeric parameter'() { expect: Functions.square(x) == r where: x << [0, 1, 2, 3, 1.5] r << [0, 1, 4, 9, 2.25] } }

Slide 35

Slide 35 text

Copyright © 2014 Russel Winder 35 Unit Test Variant 2 — #! /usr/bin/env groovy @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import spock.lang.Unroll class functionsTest_alt_1 extends Specification { @Unroll def 'square always returns the square of the numeric parameter'() { expect: Functions.square(x) == r where: [x, r] << [[0. 0], [1, 1], [2, 4], [3, 9], [1.5, 2.25]] } }

Slide 36

Slide 36 text

Copyright © 2014 Russel Winder 36 Unit Test Tabular — #! /usr/bin/env groovy @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification import spock.lang.Unroll class functionsTest_alt_1 extends Specification { @Unroll def 'square always returns the square of the numeric parameter'() { expect: Functions.square(x) == r where: x | r 0 | 0 1 | 1 2 | 4 3 | 9 1.5 | 2.25 } }

Slide 37

Slide 37 text

Copyright © 2014 Russel Winder 37 Exceptions

Slide 38

Slide 38 text

Copyright © 2014 Russel Winder 38

Slide 39

Slide 39 text

Copyright © 2014 Russel Winder 39 Code Under Test class Exceptional { def trySomething() { throw new RuntimeException('Stuff happens.') } } Exceptional.groovy

Slide 40

Slide 40 text

Copyright © 2014 Russel Winder 40 Unit Test #! /usr/bin/env groovy @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification class ExceptionalTest extends Specification { def 'trying something always results in an exception'() { given: final e = new Exceptional () when: e.trySomething() then: thrown(RuntimeException) } }

Slide 41

Slide 41 text

Copyright © 2014 Russel Winder 41 Now we can do data validation and testing of error situations.

Slide 42

Slide 42 text

Copyright © 2014 Russel Winder 42

Slide 43

Slide 43 text

Copyright © 2014 Russel Winder 43 Being More Adventurous

Slide 44

Slide 44 text

Copyright © 2014 Russel Winder 44

Slide 45

Slide 45 text

Copyright © 2014 Russel Winder 45 Spock sUnit TestNG JUnit GroovyTestCase jBehave RSpec JUnit4 BDD TDD

Slide 46

Slide 46 text

Copyright © 2014 Russel Winder 46 Specify Behaviours 1/4 – @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification class StackSpecification extends Specification { def 'newly created stacks are empty'() { given: 'a newly created stack' expect: 'the resulting stack to be empty.' }

Slide 47

Slide 47 text

Copyright © 2014 Russel Winder 47 def 'removing an item from a non-empty stack gives a value and changes the stack.'() { given: 'a new stack' and: 'an item to put on the stack' when: 'the item is added' then: 'the stack is not empty' when: 'an item is removed' then: 'the item we retrieved is the original and the stack is empty' } } Specify Behaviours 2/4 –

Slide 48

Slide 48 text

Copyright © 2014 Russel Winder 48 Specify Behaviours 3/4 – @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import spock.lang.Specification class StackSpecification extends Specification { def 'newly created stacks are empty'() { given: 'a newly created stack' def stack = new Stack () expect: 'the resulting stack to be empty.' stack.size() == 0 }

Slide 49

Slide 49 text

Copyright © 2014 Russel Winder 49 def 'removing an item from a non-empty stack gives a value and changes the stack.'() { given: 'a new stack' def stack = new Stack () and: 'an item to put on the stack' def item = 25 and: 'a variable to store the result of activity' def result when: 'the item is added' stack.push(item) then: 'the stack is not empty' stack.size() == 1 when: 'an item is removed' result = stack.pop() then: 'the item we retrieved is the original and the stack is empty' result == item && stack.size() == 0 } } Specify Behaviours 4/4 –

Slide 50

Slide 50 text

Copyright © 2014 Russel Winder 50

Slide 51

Slide 51 text

Copyright © 2014 Russel Winder 51 Closing

Slide 52

Slide 52 text

Copyright © 2014 Russel Winder 52 Hopefully everyone has had some fun and learnt some useful things.

Slide 53

Slide 53 text

Copyright © 2014 Russel Winder 53

Slide 54

Slide 54 text

Copyright © 2014 Russel Winder 54

Slide 55

Slide 55 text

Copyright © 2014 Russel Winder 55

Slide 56

Slide 56 text

Copyright © 2014 Russel Winder 56

Slide 57

Slide 57 text

Copyright © 2014 Russel Winder 57 The End

Slide 58

Slide 58 text

Copyright © 2014 Russel Winder 58 Spocktacular Testing Russel Winder email: [email protected] xmpp: [email protected] twitter: @russel_winder Web: http://www.russel.org.uk