spock: logical testing for enterprise applications
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.TRANSCRIPT
![Page 1: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/1.jpg)
SpockI have been, and always shall be, your
friendly testing framework
![Page 2: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/2.jpg)
Ken KousenKousen IT, Inc.http://[email protected]@kenkousen
Making Java Groovyhttp://manning.com/kousen
Who Am I?
![Page 3: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/3.jpg)
Testing frameworkWritten in Groovy
A logical framework for enterprise testing
Combination ofSpecification + Mock
What is Spock?
![Page 4: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/4.jpg)
Spock home pagehttp://spockframework.org
redirects to http://code.google.com/p/spock
Githubhttps://github.com/spockframework/spock
The Search for Spock
![Page 5: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/5.jpg)
Extend spock.lang.Specification
class MySpec extends Specification
Create a Spock test
![Page 6: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/6.jpg)
Demo: Palindrome Checker
Simple Specification
![Page 7: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/7.jpg)
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
![Page 8: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/8.jpg)
Test methodsdef "descriptive name"() {
// blocks}
Feature Methods
![Page 9: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/9.jpg)
setup: cleanup:given:
when:Stimulus
then:Response, booleans are checked
expect: where:
Blocks
![Page 10: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/10.jpg)
when:Contents are arbitrary
then:conditionsexceptionsinteractions (mocks described below)
Always occur together
when: and then:
![Page 11: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/11.jpg)
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
![Page 12: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/12.jpg)
Annotation for shared objectsNote: instance fields are not shared
@Shared res = new VeryExpensiveResource()
@Shared sql = Sql.newInstance(...)
@Shared
![Page 13: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/13.jpg)
Demo: Library Computer
@Shared
![Page 14: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/14.jpg)
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?
![Page 15: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/15.jpg)
Tests that iterate through dataUse where: clause
expect: name.size() == length
where:[name,length] << [['Kirk',4],['Spock',5]]
Parameterized feature methods
![Page 16: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/16.jpg)
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?
![Page 17: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/17.jpg)
Supports anything Groovy can iterate over
expect: x + y == zwhere:[x,y,z] << sql.rows('select x,y,z from ...')
where: clause
![Page 18: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/18.jpg)
Display separate messagefor each row of data
Spock 0.5: @Unroll({"...$var..."})
Spock 0.6+:@Unrolldef "my test #var ..."() { ... }
@Unroll
![Page 19: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/19.jpg)
Demos:Hello, Spock!DataDrivenDatabaseDrivenStadiumLocationsSpec
Data Specs
![Page 20: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/20.jpg)
Working with Mock objects
Interactions
interaction
NO KILL I
![Page 21: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/21.jpg)
Two syntax options:def items = Mock(List)
List items = Mock()
Can mock interfaces with standard libsMock classes with CGLIB
Creating Mocks
![Page 22: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/22.jpg)
Setting Expectations
Use >> operatorlist.get(0) >> 'data'
![Page 23: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/23.jpg)
Global:Defined outside then: blockValid to end of feature method
Local:Defined inside then: blockValid inside preceding when: block
Global vs Local
![Page 24: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/24.jpg)
No cardinalityMust have return value
then:list.get(0) >> 'data'
Optional
![Page 25: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/25.jpg)
Must have cardinalityMay have return value
then:1 * list.get(0) >> 'data'
then:3 * list.size()
Required
![Page 26: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/26.jpg)
Ranges with wildcardWildcard is _ (underscore)
3 * list.size() // 3 times(3.._) * list.size() // 3 or more(_..3) * list.size() // up to 3
Cardinalities
![Page 27: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/27.jpg)
RegexAny set method with one argpojo./set.*/(_)
Nulls, not nullpojo.method(!null)
All sorts of constraints
![Page 28: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/28.jpg)
as Operatordir.listFiles(_ as FileFilter)
Closurescount.increment { it ==~ /a*b/ }
All sorts of constraints
![Page 29: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/29.jpg)
Use multiple then blocks
def 'testing order of methods'() {when: obj.method()
then: 1*collaborator.method1()then: 1*collaborator.method2()
}
Testing Invocation Order
![Page 30: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/30.jpg)
Interactions
Demos:PublisherSubscriberTribbleSpec
![Page 31: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/31.jpg)
@Timeout
@Ignore
@IgnoreRest
@FailsWith
Extensions
![Page 32: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/32.jpg)
Test fails with expected exception
@FailsWith(TooFewInvocationsError)def "required interaction"() {
def m = Mock(List)2 * m.get(_) >> "foo"expect: m.get(3) == "foo"
}
@FailsWith
![Page 33: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/33.jpg)
Parametersvalue=ExpectedExceptionOrErrorreason="reason for failure"
@FailsWith
![Page 34: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/34.jpg)
@IgnoreDon't run a particular test or test classOptional value = reason
@IgnoreRestDon't run any OTHER tests
@Ignore and @IgnoreRest
![Page 35: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/35.jpg)
Method in Specification classTakes closure argument
def 'use interaction block'() {when: obj.method()then:interaction {
// do whatever}
}
interaction block
![Page 36: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/36.jpg)
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"
}
![Page 37: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/37.jpg)
Like most modern open source projects
Documentation can be thin or outdated
Tests are excellent
See "smoke" tests in source
Spock's Own Tests
![Page 38: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/38.jpg)
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
![Page 39: Spock: Logical Testing for Enterprise Applications](https://reader034.vdocuments.site/reader034/viewer/2022042512/5455f735af79592b448b4be1/html5/thumbnails/39.jpg)
Please complete your session evals
Session Evals