Spocktacular Testing 
Russel Winder 
email: russel@winder.org.uk 
xmpp: russel@winder.org.uk 
twitter: @russel_winder 
Web: http://www.russel.org.uk 
Copyright © 2014 Russel Winder 1
Opening 
Copyright © 2014 Russel Winder 2
Copyright © 2014 Russel Winder 3
An Historical Perspective 
Copyright © 2014 Russel Winder 4
Spock 
BDD 
jBehave 
sUnit 
TestNG 
JUnit4 
JUnit 
GroovyTestCase 
RSpec 
TDD 
Copyright © 2014 Russel Winder 5
Spock is Groovy-based… 
…but can test any JVM-based code. 
Copyright © 2014 Russel Winder 6
NB Testing frameworks support integration 
and system testing as well as unit testing. 
Copyright © 2014 Russel Winder 7
Copyright © 2014 Russel Winder 8
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. 
Copyright © 2014 Russel Winder 9
Code Under Test 
static message() { 
'Hello World.' 
} 
println message() 
helloWorld.groovy 
Copyright © 2014 Russel Winder 10
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.' 
} 
} 
Copyright © 2014 Russel Winder 11
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' 
} 
} 
Copyright © 2014 Russel Winder 12
A bit less Groovy… 
Copyright © 2014 Russel Winder 13
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 
Copyright © 2014 Russel Winder 14
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.' 
} 
} 
Copyright © 2014 Russel Winder 15
Project Structure 
. 
├── build.gradle 
└── src 
├── main 
│ └── java 
│ └── uk 
│ └── org 
│ └── winder 
│ └── spockworkshop 
│ └─- HelloWorld.java 
└── test 
└── groovy 
└── uk 
└── org 
└── winder 
└── spockworkshop 
└── unitTest_helloWorld.groovy 
Copyright © 2014 Russel Winder 16
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' 
Copyright © 2014 Russel Winder 17
Copyright © 2014 Russel Winder 18
Moving On 
Copyright © 2014 Russel Winder 19
Copyright © 2014 Russel Winder 20
Spock Test Structure 
Copyright © 2014 Russel Winder 21
given: 
Copyright © 2014 Russel Winder 22
Code Under Test 
static message() { 
'Hello World.' 
} 
println message() 
helloWorld.groovy 
Copyright © 2014 Russel Winder 23
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.' 
} 
} 
Copyright © 2014 Russel Winder 24
Another Code Under Test 
class Stuff { 
private final data = [] 
def leftShift(datum) { 
data << datum 
} 
} 
Stuff.groovy 
Copyright © 2014 Russel Winder 25
@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] 
} 
Unit Testing It 
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] 
} 
} 
Copyright © 2014 Russel Winder 26
Copyright © 2014 Russel Winder 27
Data-driven Testing 
Copyright © 2014 Russel Winder 28
Copyright © 2014 Russel Winder 29
given: 
Copyright © 2014 Russel Winder 30
Code Under Test 
Id.groovy 
class Id { 
def eval(x) { x } 
} 
Copyright © 2014 Russel Winder 31
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] 
} 
} 
Copyright © 2014 Russel Winder 32
Code Under Test 
class Functions { 
static square(x) { x * x } 
} 
Functions.groovy 
Copyright © 2014 Russel Winder 33
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] 
} 
} 
Copyright © 2014 Russel Winder 34
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]] 
} 
} 
Copyright © 2014 Russel Winder 35
#! /usr/bin/env groovy Unit Test — Tabular 
@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 
} 
} 
Copyright © 2014 Russel Winder 36
Exceptions 
Copyright © 2014 Russel Winder 37
Copyright © 2014 Russel Winder 38
Code Under Test 
class Exceptional { 
def trySomething() { 
throw new RuntimeException('Stuff happens.') 
} 
} 
Exceptional.groovy 
Copyright © 2014 Russel Winder 39
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) 
} 
} 
Copyright © 2014 Russel Winder 40
Now we can do data validation 
and 
testing of error situations. 
Copyright © 2014 Russel Winder 41
Copyright © 2014 Russel Winder 42
Being More Adventurous 
Copyright © 2014 Russel Winder 43
Copyright © 2014 Russel Winder 44
Spock 
BDD 
sUnit 
TestNG 
JUnit4 
JUnit 
GroovyTestCase 
jBehave 
RSpec 
TDD 
Copyright © 2014 Russel Winder 45
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.' 
} 
Copyright © 2014 Russel Winder 46
Specify Behaviours – 2/4 
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' 
} 
} 
Copyright © 2014 Russel Winder 47
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 
} 
Copyright © 2014 Russel Winder 48
Specify Behaviours – 4/4 
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 
} 
} 
Copyright © 2014 Russel Winder 49
Copyright © 2014 Russel Winder 50
Closing 
Copyright © 2014 Russel Winder 51
Hopefully everyone has had some fun 
and 
learnt some useful things. 
Copyright © 2014 Russel Winder 52
Copyright © 2014 Russel Winder 53
Copyright © 2014 Russel Winder 54
Copyright © 2014 Russel Winder 55
Copyright © 2014 Russel Winder 56
The End 
Copyright © 2014 Russel Winder 57
Spocktacular Testing 
Russel Winder 
email: russel@winder.org.uk 
xmpp: russel@winder.org.uk 
twitter: @russel_winder 
Web: http://www.russel.org.uk 
Copyright © 2014 Russel Winder 58

Spocktacular Testing - Russel Winder

  • 1.
    Spocktacular Testing RusselWinder email: russel@winder.org.uk xmpp: russel@winder.org.uk twitter: @russel_winder Web: http://www.russel.org.uk Copyright © 2014 Russel Winder 1
  • 2.
    Opening Copyright ©2014 Russel Winder 2
  • 3.
    Copyright © 2014Russel Winder 3
  • 4.
    An Historical Perspective Copyright © 2014 Russel Winder 4
  • 5.
    Spock BDD jBehave sUnit TestNG JUnit4 JUnit GroovyTestCase RSpec TDD Copyright © 2014 Russel Winder 5
  • 6.
    Spock is Groovy-based… …but can test any JVM-based code. Copyright © 2014 Russel Winder 6
  • 7.
    NB Testing frameworkssupport integration and system testing as well as unit testing. Copyright © 2014 Russel Winder 7
  • 8.
    Copyright © 2014Russel Winder 8
  • 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. Copyright © 2014 Russel Winder 9
  • 10.
    Code Under Test static message() { 'Hello World.' } println message() helloWorld.groovy Copyright © 2014 Russel Winder 10
  • 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.' } } Copyright © 2014 Russel Winder 11
  • 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' } } Copyright © 2014 Russel Winder 12
  • 13.
    A bit lessGroovy… Copyright © 2014 Russel Winder 13
  • 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 Copyright © 2014 Russel Winder 14
  • 15.
    Unit Test packageuk.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.' } } Copyright © 2014 Russel Winder 15
  • 16.
    Project Structure . ├── build.gradle └── src ├── main │ └── java │ └── uk │ └── org │ └── winder │ └── spockworkshop │ └─- HelloWorld.java └── test └── groovy └── uk └── org └── winder └── spockworkshop └── unitTest_helloWorld.groovy Copyright © 2014 Russel Winder 16
  • 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' Copyright © 2014 Russel Winder 17
  • 18.
    Copyright © 2014Russel Winder 18
  • 19.
    Moving On Copyright© 2014 Russel Winder 19
  • 20.
    Copyright © 2014Russel Winder 20
  • 21.
    Spock Test Structure Copyright © 2014 Russel Winder 21
  • 22.
    given: Copyright ©2014 Russel Winder 22
  • 23.
    Code Under Test static message() { 'Hello World.' } println message() helloWorld.groovy Copyright © 2014 Russel Winder 23
  • 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.' } } Copyright © 2014 Russel Winder 24
  • 25.
    Another Code UnderTest class Stuff { private final data = [] def leftShift(datum) { data << datum } } Stuff.groovy Copyright © 2014 Russel Winder 25
  • 26.
    @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] } Unit Testing It 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] } } Copyright © 2014 Russel Winder 26
  • 27.
    Copyright © 2014Russel Winder 27
  • 28.
    Data-driven Testing Copyright© 2014 Russel Winder 28
  • 29.
    Copyright © 2014Russel Winder 29
  • 30.
    given: Copyright ©2014 Russel Winder 30
  • 31.
    Code Under Test Id.groovy class Id { def eval(x) { x } } Copyright © 2014 Russel Winder 31
  • 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] } } Copyright © 2014 Russel Winder 32
  • 33.
    Code Under Test class Functions { static square(x) { x * x } } Functions.groovy Copyright © 2014 Russel Winder 33
  • 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] } } Copyright © 2014 Russel Winder 34
  • 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]] } } Copyright © 2014 Russel Winder 35
  • 36.
    #! /usr/bin/env groovyUnit Test — Tabular @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 } } Copyright © 2014 Russel Winder 36
  • 37.
    Exceptions Copyright ©2014 Russel Winder 37
  • 38.
    Copyright © 2014Russel Winder 38
  • 39.
    Code Under Test class Exceptional { def trySomething() { throw new RuntimeException('Stuff happens.') } } Exceptional.groovy Copyright © 2014 Russel Winder 39
  • 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) } } Copyright © 2014 Russel Winder 40
  • 41.
    Now we cando data validation and testing of error situations. Copyright © 2014 Russel Winder 41
  • 42.
    Copyright © 2014Russel Winder 42
  • 43.
    Being More Adventurous Copyright © 2014 Russel Winder 43
  • 44.
    Copyright © 2014Russel Winder 44
  • 45.
    Spock BDD sUnit TestNG JUnit4 JUnit GroovyTestCase jBehave RSpec TDD Copyright © 2014 Russel Winder 45
  • 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.' } Copyright © 2014 Russel Winder 46
  • 47.
    Specify Behaviours –2/4 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' } } Copyright © 2014 Russel Winder 47
  • 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 } Copyright © 2014 Russel Winder 48
  • 49.
    Specify Behaviours –4/4 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 } } Copyright © 2014 Russel Winder 49
  • 50.
    Copyright © 2014Russel Winder 50
  • 51.
    Closing Copyright ©2014 Russel Winder 51
  • 52.
    Hopefully everyone hashad some fun and learnt some useful things. Copyright © 2014 Russel Winder 52
  • 53.
    Copyright © 2014Russel Winder 53
  • 54.
    Copyright © 2014Russel Winder 54
  • 55.
    Copyright © 2014Russel Winder 55
  • 56.
    Copyright © 2014Russel Winder 56
  • 57.
    The End Copyright© 2014 Russel Winder 57
  • 58.
    Spocktacular Testing RusselWinder email: russel@winder.org.uk xmpp: russel@winder.org.uk twitter: @russel_winder Web: http://www.russel.org.uk Copyright © 2014 Russel Winder 58