SlideShare a Scribd company logo
Spock
I have been, and always shall be, your
      friendly testing framework
Who Am I?
Ken Kousen
Kousen IT, Inc.
http://www.kousenit.com
ken.kousen@kousenit.com
@kenkousen

Making Java Groovy
http://manning.com/kousen
What is Spock?
Testing framework
  Written in Groovy

  A logical framework for enterprise testing

  Combination of
    Specification + Mock
The Search for Spock
Spock home page
  http://spockframework.org
     redirects to
  http://code.google.com/p/spock

Github
   https://github.com/spockframework/spock
Create a Spock test
Extend spock.lang.Specification

  class MySpec extends Specification
Simple Specification
Demo: Palindrome Checker
Fixture Methods

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
Feature Methods
Test methods
  def "descriptive name"() {
    // blocks
  }
Blocks
setup:     cleanup:
given:

when:
  Stimulus
then:
  Response, booleans are checked

expect:    where:
when: and then:
when:
  Contents are arbitrary

then:
   conditions
   exceptions
   interactions (mocks described below)

Always occur together
what they thought old Kirk
old Method                                           would look like




Sweet method in Specification class

  expression value before
  where block

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


                  what he actually looks like
@Shared
Annotation for shared objects
  Note: instance fields are not shared

  @Shared res = new VeryExpensiveResource()

  @Shared sql = Sql.newInstance(...)
@Shared
Demo: Library Computer
are exceptions evil or just
Exceptions                                goatees?




thrown() and notThrown()

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


Can do work after catching exception
Parameterized feature methods
Tests that iterate through data
  Use where: clause

  expect: name.size() == length

  where:
  [name,length] << [['Kirk',4],['Spock',5]]
Data Table
where: clause supports data tables

  expect:    name.size() == length
  where:
   name      |   length              Shouldn't Data run on
                                          Android?

   'Kirk'    |   4
  'Spock'    |   5
  'McCoy'    |   5
where: clause
Supports anything Groovy can iterate over

  expect: x + y == z
  where:
  [x,y,z] << sql.rows('select x,y,z from ...')
@Unroll
Display separate message
   for each row of data

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

Spock 0.6+:
  @Unroll
  def "my test #var ..."() { ... }
Data Specs
Demos:
  Hello, Spock!
  DataDriven
  DatabaseDriven
  StadiumLocationsSpec
Interactions
Working with Mock objects




       interaction




                            NO KILL I
Creating Mocks
Two syntax options:
  def items = Mock(List)

  List items = Mock()

  Can mock interfaces with standard libs
  Mock classes with CGLIB
Setting Expectations
Use >> operator
  list.get(0) >> 'data'
Global vs Local
Global:
  Defined outside then: block
  Valid to end of feature method

Local:
  Defined inside then: block
  Valid inside preceding when: block
Optional
No cardinality
Must have return value

  then:
  list.get(0) >> 'data'
Required
Must have cardinality
May have return value

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

  then:
  3 * list.size()
Cardinalities
Ranges with wildcard
  Wildcard is _ (underscore)

  3 * list.size()          // 3 times
  (3.._) * list.size()     // 3 or more
  (_..3) * list.size()     // up to 3
All sorts of constraints
Regex
  Any set method with one arg
  pojo./set.*/(_)

Nulls, not null
  pojo.method(!null)
All sorts of constraints
as Operator
  dir.listFiles(_ as FileFilter)

Closures
  count.increment { it ==~ /a*b/ }
Testing Invocation Order
Use multiple then blocks

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

      then: 1*collaborator.method1()
      then: 1*collaborator.method2()
  }
Interactions
Demos:
  PublisherSubscriber
  TribbleSpec
Extensions
@Timeout

@Ignore

@IgnoreRest

@FailsWith
@FailsWith
Test fails with expected exception

  @FailsWith(TooFewInvocationsError)
  def "required interaction"() {
    def m = Mock(List)
    2 * m.get(_) >> "foo"
    expect: m.get(3) == "foo"
  }
@FailsWith
Parameters
  value=ExpectedExceptionOrError
  reason="reason for failure"
@Ignore and @IgnoreRest
@Ignore
  Don't run a particular test or test class
  Optional value = reason

@IgnoreRest
  Don't run any OTHER tests
interaction block
Method in Specification class
  Takes closure argument

  def 'use interaction block'() {
    when: obj.method()
    then:
    interaction {
       // do whatever
    }
  }
BDD
Behavior Driven Development
    Each block accepts string description
    Just 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"
    }
Spock's Own Tests
Like most modern open source projects

  Documentation can be thin or outdated

  Tests are excellent

     See "smoke" tests in source
Links
http://github.com/spockframework/spock
http://code.google.com/p/spock
http://spockframework.org
http://meet.spockframework.org
http://groups.google.com/group/spockframework?pli=1

Source code for examples is from
1. spock-example project
    https://github.com/spockframework/spock-example
2. my GitHub repo
    https://github.com/kousen/Spock-NFJS-Article
Session Evals
Please complete your session evals

More Related Content

Spock: Test Well and Prosper