Spock: Logical Testing for Enterprise Applications

Preview:

DESCRIPTION

Speaker: Kenneth Kousen The Spock framework brings simple, elegant testing to Java and Groovy projects. It integrates cleanly with JUnit, so Spock tests can be integrated as part of an existing test suite. Spock also includes an embedded mocking framework that can be used right away. In this presentation, we'll look at several examples of Spock tests and review most of its capabilities, including mock objects and integration with Spring.

Citation preview

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

Recommended