spock: test well and prosper
DESCRIPTION
Demonstrates the basics of the Spock framework for unit testing Java and Groovy applicationsTRANSCRIPT
SpockI have been, and always shall be, your
friendly testing framework
Ken KousenKousen IT, Inc.http://[email protected]@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