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

Spocktacular Testing - Russel Winder

Embed Size (px)

Citation preview

Copyright © 2014 Russel Winder 1

Spocktacular Testing

Russel Winder

email: [email protected]: [email protected]

twitter: @russel_winderWeb: http://www.russel.org.uk

Copyright © 2014 Russel Winder 2

Opening

Copyright © 2014 Russel Winder 3

Copyright © 2014 Russel Winder 4

An Historical Perspective

Copyright © 2014 Russel Winder 5

Spock

sUnit

TestNG

JUnit

GroovyTestCase

jBehave

RSpec

JUnit4

BDD

TDD

Copyright © 2014 Russel Winder 6

Spock is Groovy-based…

…but can test any JVM-based code.

Copyright © 2014 Russel Winder 7

NB Testing frameworks support integrationand system testing as well as unit testing.

Copyright © 2014 Russel Winder 8

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.

Copyright © 2014 Russel Winder 10

Code Under Test

static message() { 'Hello World.'}

println message()

helloWorld.groovy

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.' }}

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' }}

Copyright © 2014 Russel Winder 13

A bit less Groovy…

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

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.' }}

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

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'

Copyright © 2014 Russel Winder 18

Copyright © 2014 Russel Winder 19

Moving On

Copyright © 2014 Russel Winder 20

Copyright © 2014 Russel Winder 21

Spock Test Structure

Copyright © 2014 Russel Winder 22

given:

Copyright © 2014 Russel Winder 23

Code Under Test

static message() { 'Hello World.'}

println message()

helloWorld.groovy

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.' }}

Copyright © 2014 Russel Winder 25

Another Code Under Test

class Stuff { private final data = [] def leftShift(datum) { data << datum }}

Stuff.groovy

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] }}

Copyright © 2014 Russel Winder 27

Copyright © 2014 Russel Winder 28

Data-driven Testing

Copyright © 2014 Russel Winder 29

Copyright © 2014 Russel Winder 30

given:

Copyright © 2014 Russel Winder 31

Code Under Test

Id.groovy

class Id { def eval(x) { x }}

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.Specificationimport 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 33

Code Under Test

class Functions { static square(x) { x * x }}

Functions.groovy

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.Specificationimport 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 35

Unit Test Variant 2—

#! /usr/bin/env groovy

@Grab('org.spockframework:spock-core:0.7-groovy-2.0')import spock.lang.Specificationimport 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

Unit Test Tabular—#! /usr/bin/env groovy

@Grab('org.spockframework:spock-core:0.7-groovy-2.0')import spock.lang.Specificationimport 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 37

Exceptions

Copyright © 2014 Russel Winder 38

Copyright © 2014 Russel Winder 39

Code Under Test

class Exceptional { def trySomething() { throw new RuntimeException('Stuff happens.') }}

Exceptional.groovy

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) }}

Copyright © 2014 Russel Winder 41

Now we can do data validationand

testing of error situations.

Copyright © 2014 Russel Winder 42

Copyright © 2014 Russel Winder 43

Being More Adventurous

Copyright © 2014 Russel Winder 44

Copyright © 2014 Russel Winder 45

Spock

sUnit

TestNG

JUnit

GroovyTestCase

jBehaveRSpec

JUnit4

BDD

TDD

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.' }

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–

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 }

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–

Copyright © 2014 Russel Winder 50

Copyright © 2014 Russel Winder 51

Closing

Copyright © 2014 Russel Winder 52

Hopefully everyone has had some funand

learnt some useful things.

Copyright © 2014 Russel Winder 53

Copyright © 2014 Russel Winder 54

Copyright © 2014 Russel Winder 55

Copyright © 2014 Russel Winder 56

Copyright © 2014 Russel Winder 57

The End

Copyright © 2014 Russel Winder 58

Spocktacular Testing

Russel Winder

email: [email protected]: [email protected]

twitter: @russel_winderWeb: http://www.russel.org.uk