Spock: Test Well and Prosper

Post on 25-Jan-2015

2.276 views 6 download

description

Demonstrates the basics of the Spock framework for unit testing Java and Groovy applications

Transcript of Spock: Test Well and Prosper

SpockI have been, and always shall be, your

friendly testing framework

Ken KousenKousen IT, Inc.http://www.kousenit.comken.kousen@kousenit.com@kenkousen

Making Java Groovyhttp://manning.com/kousen

Who Am I?

Testing frameworkWritten in Groovy

A logical framework for enterprise testing

Combination ofSpecification + Mock

What is Spock?

Spock home pagehttp://spockframework.org

redirects to http://code.google.com/p/spock

Githubhttps://github.com/spockframework/spock

The Search for Spock

Extend spock.lang.Specification

class MySpec extends Specification

Create a Spock test

Demo: Palindrome Checker

Simple Specification

def setup() {} run before every feature method

def cleanup() {} run after every feature method

def setupSpec() {} run before first feature method

def cleanupSpec() {} run after last feature method

Like JUnit 4: @Before, @After, @BeforeClass, @AfterClass

Fixture Methods

Test methodsdef "descriptive name"() {

// blocks}

Feature Methods

setup: cleanup:given:

when:Stimulus

then:Response, booleans are checked

expect: where:

Blocks

when:Contents are arbitrary

then:conditionsexceptionsinteractions (mocks described below)

Always occur together

when: and then:

Sweet method in Specification class

expression value beforewhere block

when: obj.count()then:count == old(count) + 1

old Method what they thought old Kirk would look like

what he actually looks like

Annotation for shared objectsNote: instance fields are not shared

@Shared res = new VeryExpensiveResource()

@Shared sql = Sql.newInstance(...)

@Shared

Demo: Library Computer

@Shared

thrown() and notThrown()

then:thrown(SqlException)

-- or --SqlException e = thrown()e.sqlCode == ...

Can do work after catching exception

Exceptions are exceptions evil or just goatees?

Tests that iterate through dataUse where: clause

expect: name.size() == length

where:[name,length] << [['Kirk',4],['Spock',5]]

Parameterized feature methods

where: clause supports data tables

expect: name.size() == lengthwhere: name | length 'Kirk' | 4'Spock' | 5'McCoy' | 5

Data Table

Shouldn't Data run on Android?

Supports anything Groovy can iterate over

expect: x + y == zwhere:[x,y,z] << sql.rows('select x,y,z from ...')

where: clause

Display separate messagefor each row of data

Spock 0.5: @Unroll({"...$var..."})

Spock 0.6+:@Unrolldef "my test #var ..."() { ... }

@Unroll

Demos:Hello, Spock!DataDrivenDatabaseDrivenStadiumLocationsSpec

Data Specs

Working with Mock objects

Interactions

interaction

NO KILL I

Two syntax options:def items = Mock(List)

List items = Mock()

Can mock interfaces with standard libsMock classes with CGLIB

Creating Mocks

Setting Expectations

Use >> operatorlist.get(0) >> 'data'

Global:Defined outside then: blockValid to end of feature method

Local:Defined inside then: blockValid inside preceding when: block

Global vs Local

No cardinalityMust have return value

then:list.get(0) >> 'data'

Optional

Must have cardinalityMay have return value

then:1 * list.get(0) >> 'data'

then:3 * list.size()

Required

Ranges with wildcardWildcard is _ (underscore)

3 * list.size() // 3 times(3.._) * list.size() // 3 or more(_..3) * list.size() // up to 3

Cardinalities

RegexAny set method with one argpojo./set.*/(_)

Nulls, not nullpojo.method(!null)

All sorts of constraints

as Operatordir.listFiles(_ as FileFilter)

Closurescount.increment { it ==~ /a*b/ }

All sorts of constraints

Use multiple then blocks

def 'testing order of methods'() {when: obj.method()

then: 1*collaborator.method1()then: 1*collaborator.method2()

}

Testing Invocation Order

Interactions

Demos:PublisherSubscriberTribbleSpec

@Timeout

@Ignore

@IgnoreRest

@FailsWith

Extensions

Test fails with expected exception

@FailsWith(TooFewInvocationsError)def "required interaction"() {

def m = Mock(List)2 * m.get(_) >> "foo"expect: m.get(3) == "foo"

}

@FailsWith

Parametersvalue=ExpectedExceptionOrErrorreason="reason for failure"

@FailsWith

@IgnoreDon't run a particular test or test classOptional value = reason

@IgnoreRestDon't run any OTHER tests

@Ignore and @IgnoreRest

Method in Specification classTakes closure argument

def 'use interaction block'() {when: obj.method()then:interaction {

// do whatever}

}

interaction block

BDD

Behavior Driven DevelopmentEach block accepts string descriptionJust documentation

def "number of tribbles in storage compartment"() {

given: "average litter of 10"

and: "new generation every 12 hours over a period of three days"

when: "tribbles get into storage compartments"

then: "compute number of tribbles"

}

Like most modern open source projects

Documentation can be thin or outdated

Tests are excellent

See "smoke" tests in source

Spock's Own Tests

http://github.com/spockframework/spockhttp://code.google.com/p/spockhttp://spockframework.orghttp://meet.spockframework.orghttp://groups.google.com/group/spockframework?pli=1

Source code for examples is from1. spock-example project

https://github.com/spockframework/spock-example2. my GitHub repo

https://github.com/kousen/Spock-NFJS-Article

Links

Please complete your session evals

Session Evals