SlideShare a Scribd company logo
Smarter Testing
  With Spock

             Dmitry Voloshko
                 03/11/2012
What we’ll talk about
Spock?!

State Based Testing

Data Driven Testing

Interaction Based Testing

Spock Extensions

More Cool Stuff
Spock?!
Spock is...
A developer testing framework...

for Groovy and Java applications...

based on Groovy...

fully compatible with JUnit...

but going beyond!
Spock Can...
Reduce the lines of test code

Make tests more readable

Turn tests into specifications

Be extended in powerful ways

Bring back the fun to testing!
Getting Started
Homepage
http://spockframework.org

Source Code
https://github.com/spockframework/spock

Spock Web Console
http://meet.spockframework.org

Spock Example Project
http://downloads.spockframework.org
https://github.com/spockframework/spock/tree/groovy-1.8/spock-
example
Who’s Using Spock?
     Gradle       GPars
   Grails             Geb

  Grails Plugin Collective

     Apache Tapestry

     Griffon      Spock
            Spring?
Who’s Using Spock?
             Betfair            be2
     bemoko          BSkyB      CTI Digital
       Donewtech           Solutions
                  eHarmony
Energized Work             Gennemtænkt IT
   IntelliGrape Software             Netflix
Smarter Ecommerce          STERMEDIA Sp. z o.o.
        Software Projects Spot Diving
            SystemsForge       TouK
State Based Testing
State Based Testing
Classical Unit Testing
  Arrange
  Act
  Assert

Given-When-Then
The Code For Testing
Account.java
public class Account {
    private BigDecimal balance = new BigDecimal(0);

    public Account(BigDecimal initial) {
      balance = initial;
    }

    public BigDecimal getBalance() {
      return balance;
    }

    public void withdraw(BigDecimal amount) {
      if (amount.compareTo(BigDecimal.ZERO) < 0) {
         throw new NegativeAmountWithdrawnException(amount);
      }
      balance = balance.subtract(amount);
    }
}
The Code For Testing
NegativeAmountWithdrawnException.java


public class NegativeAmountWithdrawnException extends RuntimeException {
    private final BigDecimal amount;

    public NegativeAmountWithdrawnException(BigDecimal amount) {
      super("cannot withdraw" + amount);
      this.amount = amount;
    }

    public BigDecimal getAmount() {
      return amount;
    }
}
Show me the code
public class AccountTest {
  @Test
  public void withdrawSomeAmount() {
    // given
    Account account = new Account(BigDecimal.valueOf(5));

        // when
        account.withdraw(BigDecimal.valueOf(2));

        // then
        assertEquals(BigDecimal.valueOf(3), account.getBalance());
    }
}
Show me the code
class AccountSpec extends Specification {

    def "withdraw some amount"() {
      given:
      Account account = new Account(BigDecimal.valueOf(5));

        when:
        account.withdraw(BigDecimal.valueOf(2));

        then:
        account.getBalance() == BigDecimal.valueOf(3);
    }
}
Show me the code
class AccountSpec2 extends Specification {

    def "withdraw some amount"() {
      given:
      def account = new Account(5.0)

        when:
        account.withdraw(2.0)

        then:
        account.balance == 3.0
    }
}
Show me the code
class AccountSpec3 extends Specification {

    def "withdraw some amount"() {
      given: "an account with a balance of five euros"
      def account = new Account(5.0)

        when: "two euros are withdrawn"
        account.withdraw(2.0)

        then: "three euros remain in the account"
        account.balance == 3.0
    }
}
Show me the code
class AccountSpec4 extends Specification {
  def "can't withdraw a negative amount"() {
     given:
     def account = new Account(5.0)

        when:
        account.withdraw(-1.0)

        then:
        NegativeAmountWithdrawnException e = thrown()
        e.amount == -1.0
    }

    def "withdrawing some amount decreases the balance by exactly that amount"() {
      def account = new Account(5.0)

        when:
        account.withdraw(2.0)

        then:
        account.balance == old(account.balance) - 2.0
    }
}
Show me the code
class SharedField extends Specification {
   @Shared File file

    def "a file based test"() {
      when:
      file = new File("foo.txt")
      file.createNewFile()

        then:
        file.exists()
    }

    def "by now the object is not null"() {
      expect:
      file.exists()

        cleanup:
        file.delete()
    }
}
Show me the code
class SetupSpecSpec extends Specification {
   File file

    def setup() {
      file = new File("foo2.txt")
    }

    def "a file based test"() {
      when:
      file.createNewFile()

        then:
        file.exists()
    }

    def "by now the object is not null"() {
      expect: file.exists()
      cleanup: file.delete()
    }
}
Show me the code
class Conditions extends Specification {
  def "when-then style"() {
     when:
     def x = Math.max(5, 9)

        then:
        x == 9
    }

    def "expect style"() {
      expect:
      Math.max(5, 9) == 9
    }

    def "more complex conditions"() {
      expect:
      germanCarBrands.any { it.size() >= 3 }
    }

    private getGermanCarBrands() { ["audi", "bmw", "porsche"] }
}
Recap: State Based Testing
Blocks
setup: cleanup: expect: given: when: then:
where: and:

Fixture Methods
setup() cleanup() setupSpec() cleanupSpec()

Instance and @Shared fields

old() and thrown()
Data Driven Testing
Data Driven Testing


Test the same behavior...

with varying data!
Show me the code
class AccountSpecDataDriven extends Specification {
  @Unroll
  def "withdraw some amount"() {
     given:
     def account = new Account(balance)

        when:
        account.withdraw(withdrawn)

        then:
        account.balance == remaining

        where:
        balance | withdrawn | |remaining
        5.0     | 2.0       | | 3.0
        4.0     | 0.0       | | 4.0
        4.0     | 4.0       | | 0.0
    }
}
Show me the code
class AccountSpecDataDriven extends Specification {
  @Unroll
  def "withdrawing #withdrawn from account with balance #balance"() {
     given:
     def account = new Account(balance)

        when:
        account.withdraw(withdrawn)

        then:
        account.balance == old(account.balance) – withdrawn

        where:
        balance | withdrawn
        5.0     | 2.0
        4.0     | 0.0
        4.0     | 4.0
    }
}
Show me the code
class AccountSpecDatabaseDriven extends Specification {
  @Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")

    def setupSpec() {
      sql.execute("create table accountdata (id int primary key, balance decimal, withdrawn decimal, remaining decimal)")
      sql.execute("insert into accountdata values (1, 5.0, 2.0, 3.0), (2, 4.0, 0.0, 4.0), (3, 4.0, 4.0, 0.0)")
    }

    @Unroll def "withdrawing #withdrawn from account with balance #balance leaves #remaining"() {
     given:
     def account = new Account(balance)

        when:
        account.withdraw(withdrawn)

        then:
        account.balance == remaining

        where:
        [balance, withdrawn, remaining] << sql.rows("select balance, withdrawn, remaining from accountdata")
    }
}
Recap: Data Driven Testing

where: block

Data tables

External data sources

@Unroll
Interaction Based Testing
Interaction Based Testing

Design and test how your objects
communicate

Mocking frameworks to the rescue

Spock comes with its own mocking
framework
The Code For Testing
PublisherSubscriber.groovy

interface Subscriber {
    void receive(String message)
}

class Publisher {
  List<Subscriber> subscribers = []

    void publish(String message) {
      for (subscriber in subscribers) {
        try {
            subscriber.receive(message)
        } catch (ignored) {}
      }
    }
}
The Code For Testing
PublisherSubscriber.groovy
interface Subscriber2 {
    void receive(String message)
    boolean isActive()
}

class Publisher2 {
  List<Subscriber2> subscribers = []

    void publish(String message) {
      for (subscriber in subscribers) {
        try {
           if (subscriber.active) {
              subscriber.receive(message)
           }
        } catch (ignored) {}
      }
    }
}
Show me the code
class PublisherSubscriberSpec extends Specification {
  def pub = new Publisher()
  def sub1 = Mock(Subscriber)
  def sub2 = Mock(Subscriber)

    def setup() {
      pub.subscribers << sub2 << sub1
    }

    def "delivers messages to all subscribers"() {
      when:
      pub.publish("msg")

        then:
        1 * sub1.receive("msg")
        1 * sub2.receive("msg")
    }
}
Show me the code
class PublisherSubscriberSpec2 extends Specification {
  def pub = new Publisher()
  def sub1 = Mock(Subscriber)

    def setup() {
      pub.subscribers << sub1
    }

    def "delivers messages in the order they are published"() {
      when:
      pub.publish("msg1")
      pub.publish("msg2")

        then:
        1 * sub1.receive("msg1")

        then:
        1 * sub1.receive("msg2")
    }
}
Show me the code
class PublisherSubscriber2Spec extends Specification {
  def pub = new Publisher2()
  def sub1 = Mock(Subscriber2)
  def sub2 = Mock(Subscriber2)

    def setup() {
      pub.subscribers << sub1 << sub2
    }

    def "delivers messages to all active subscribers"() {
      sub1.active >> true
      sub2.active >> false

        when:
        pub.publish("msg")

        then:
        1 * sub1.receive("msg")
        0 * sub2.receive(_)
    }
}
Recap: Interaction Based Testing
  Creating
  def sub = Mock(Subscriber)
  Subscriber sub = Mock()


  Mocking
  1 * sub.receive("msg")
  (1..3) * sub.receive(_)
  (1.._) * sub.receive(_ as String)
  1 * sub.receive(!null)
  1 * sub.receive({it.contains("m")})
  1 * _./rec.*/("msg")
Recap: Interaction Based Testing
  Stubbing
  // now returns status code
  String receive(String msg) { ... }

  sub.receive(_) >> "ok"
  sub.receive(_) >>> ["ok", "ok", "fail"]
  sub.receive(_) >>> { msg -> msg.size() > 3 ? "ok" : "fail" }

  Mocking and Stubbing
  3 * sub.receive(_) >>> ["ok", "ok", "fail"]


  Impressing your friends
  (_.._) * _._(*_) >> _
Spock Extensions
Spock Extensions

Listeners

Interceptors

Annotation-driven extensions

Global extensions
Built-in Extensions
@Ignore
@IgnoreRest
@FailsWith
@Timeout
@AutoCleanup
@Stepwise
@RevertMetaClass
@Rule
Show me the code
class JUnitRules extends Specification {
  @Rule TemporaryFolder tempFolder
  @Shared File file

    def "a file based test"() {
      when:
      file = tempFolder.newFile("foo.txt")

        then:
        file.exists()
    }

    def "by now the file has been deleted"() {
      expect:
      !file.exists()
    }
}
Show me the code
@Stepwise
class StepwiseSpec extends Specification {
  def "step 1"() {
     expect: true
  }

    def "step 2"() {
      expect: true
    }

    def "step 3"() {
      expect: true
    }
}
External Extensions
spock-grails
spock-spring
spock-guice
spock-tapestry
spock-unitils


spock-griffon
spock-arquillian
spock-extensions http://github.com/robfletcher/spock-extensions
Grails Extensions
http://grails.org/plugin/spock

https://github.com/spockframework/spock-grails

grails install plugin spock 0.6

grails test-app

grails test-app unit:TestSpec
Grails Extensions
@TestFor(MouthService)
@Mock([Patient, PatientMouth, PatientTooth])
class MouthServiceSpec extends Specification {
   def "Get patient tooth by index"() {
     setup: "Create domain mocks"
        def patient = new Patient(dateOfBirth: new Date('05/03/1984')).save(false)
        def patientTooth = new PatientTooth(index: 10, toothCode: "10").save(false)
        def patientMouth = new PatientMouth(patient: patient, patientTeeth: [patientTooth]).save(false)

        when:
         patientTooth = service.getPatientToothByIndex(patientMouth, index)

        then:
          patientTooth.toothCode == tooth
          patientMouth.patientTeeth.contains(patientTooth)

        where:
          index | tooth
          10 | "10"
          20 | null
    }
}
Spring Extension
class InjectionExamples extends Specification {
   @Autowired
   Service1 byType

    @Resource
    Service1 byName

    @Autowired
    ApplicationContext context
}
Other Cool Stuff
Configuring Spock
~/.spock/SpockConfig.groovy, or on class path, or with -Dspock.configuration

runner {
    filterStackTrace false
    include Fast
    exclude Slow
    optimizeRunOrder true
}

@Fast
class MyFastSpec extends Specification {
     def "I’m fast as hell!"() { expect: true }

    @Slow
    def “Sorry, can’t keep up..."() {expect: false }
}
Tooling

Eclipse, IDEA

Ant, Maven, Gradle

Jenkins, Bamboo, TeamCity

Spock runs everywhere JUnit and Groovy run!
Spock Under The Hood
You write...
a = 1; b = 2; c = 4
expect: sum(a, b) == c


Spock generates...
def rec = new ValueRecorder()
verifier.expect(
  rec.record(rec.record(sum(rec.record(a),
              rec.record(b)) == rec.record(c)))

 You see...
  sum (a, b) == c
  |    | | | |
  3    12 | 4
            false
Q&A
Homepage
http://spockframework.org


Source Code
https://github.com/spockframework/spock


Spock Web Console
http://meet.spockframework.org


Spock Example Project
http://downloads.spockframework.org
https://github.com/spockframework/spock/tree/groovy-1.8/spock-example

More Related Content

PDF
Spock Framework
PDF
Spock framework
PDF
Spock: Test Well and Prosper
PPTX
Smarter Testing with Spock
PDF
Spock Testing Framework - The Next Generation
PDF
Spock: A Highly Logical Way To Test
PPT
Unit testing with Spock Framework
PPTX
Unit/Integration Testing using Spock
Spock Framework
Spock framework
Spock: Test Well and Prosper
Smarter Testing with Spock
Spock Testing Framework - The Next Generation
Spock: A Highly Logical Way To Test
Unit testing with Spock Framework
Unit/Integration Testing using Spock

What's hot (20)

PDF
Grails/Groovyによる開発事例紹介
PPT
Ggug spock
PDF
PPT
PPTX
PDF
DCN Practical
PPTX
Unit testing patterns for concurrent code
PDF
Clojure - A new Lisp
PPTX
Building unit tests correctly
PPT
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
Java 7 LavaJUG
DOCX
Advance Java Programs skeleton
PDF
Introduction to web programming for java and c# programmers by @drpicox
DOC
Ad java prac sol set
KEY
Inside PyMongo - MongoNYC
PDF
Software Testing - Invited Lecture at UNSW Sydney
PPT
Unit testing
PDF
Pyconie 2012
PPTX
Javascript Testing with Jasmine 101
Grails/Groovyによる開発事例紹介
Ggug spock
DCN Practical
Unit testing patterns for concurrent code
Clojure - A new Lisp
Building unit tests correctly
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 LavaJUG
Advance Java Programs skeleton
Introduction to web programming for java and c# programmers by @drpicox
Ad java prac sol set
Inside PyMongo - MongoNYC
Software Testing - Invited Lecture at UNSW Sydney
Unit testing
Pyconie 2012
Javascript Testing with Jasmine 101
Ad

Viewers also liked (18)

PPTX
Geb with spock
PDF
Taming Functional Web Testing with Spock and Geb
PDF
Java Testing With Spock - Ken Sipe (Trexin Consulting)
PDF
Idiomatic spock
PDF
Codemotion 2015 spock_workshop
PPTX
Westrich spock-assets-gum
PPTX
Spock - the next stage of unit testing
PDF
TDD with Spock @xpdays_ua
PDF
Spring puzzlers
PDF
Unit test-using-spock in Grails
PPTX
Vert.x 세미나 이지원_배포용
PPTX
SeConf2015: Advanced Automated Visual Testing With Selenium
PDF
Spring Cloud Contract And Your Microservice Architecture
PDF
Testing a 2D Platformer with Spock
ODP
Fabulous Tests on Spock and Groovy
PDF
Spock Extensions Anatomy
ODP
Spring cloud for microservices architecture
PDF
Consumer Driven Contracts and Your Microservice Architecture
Geb with spock
Taming Functional Web Testing with Spock and Geb
Java Testing With Spock - Ken Sipe (Trexin Consulting)
Idiomatic spock
Codemotion 2015 spock_workshop
Westrich spock-assets-gum
Spock - the next stage of unit testing
TDD with Spock @xpdays_ua
Spring puzzlers
Unit test-using-spock in Grails
Vert.x 세미나 이지원_배포용
SeConf2015: Advanced Automated Visual Testing With Selenium
Spring Cloud Contract And Your Microservice Architecture
Testing a 2D Platformer with Spock
Fabulous Tests on Spock and Groovy
Spock Extensions Anatomy
Spring cloud for microservices architecture
Consumer Driven Contracts and Your Microservice Architecture
Ad

Similar to Smarter Testing With Spock (20)

PDF
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
PDF
G*ワークショップ in 仙台 Grails(とことん)入門
KEY
Why ruby
PDF
Testowanie JavaScript
PDF
Spock the enterprise ready specifiation framework - Ted Vinke
PDF
Kitura Todolist tutorial
KEY
What's New In Python 2.6
PDF
Introduction to-mongo db-execution-plan-optimizer-final
PDF
Introduction to Mongodb execution plan and optimizer
PDF
Fun Teaching MongoDB New Tricks
PDF
Solid scala
PDF
Coding in Style
PPSX
Javascript variables and datatypes
PDF
Overview of The Scala Based Lift Web Framework
PDF
Scala based Lift Framework
PDF
Overview Of Lift Framework
PDF
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
PDF
Funcitonal Swift Conference: The Functional Way
PDF
用Tornado开发RESTful API运用
PDF
Hidden Docs in Angular
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
G*ワークショップ in 仙台 Grails(とことん)入門
Why ruby
Testowanie JavaScript
Spock the enterprise ready specifiation framework - Ted Vinke
Kitura Todolist tutorial
What's New In Python 2.6
Introduction to-mongo db-execution-plan-optimizer-final
Introduction to Mongodb execution plan and optimizer
Fun Teaching MongoDB New Tricks
Solid scala
Coding in Style
Javascript variables and datatypes
Overview of The Scala Based Lift Web Framework
Scala based Lift Framework
Overview Of Lift Framework
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
Funcitonal Swift Conference: The Functional Way
用Tornado开发RESTful API运用
Hidden Docs in Angular

More from IT Weekend (20)

PPTX
Quality attributes testing. From Architecture to test acceptance
PPTX
Mobile development for JavaScript developer
PPTX
Building an Innovation & Strategy Process
PDF
IT Professionals – The Right Time/The Right Place
PDF
Building a Data Driven Organization
PPT
7 Tools for the Product Owner
PPTX
Hacking your Doorbell
PPTX
An era of possibilities, a window in time
PPTX
Web services automation from sketch
PPTX
Why Ruby?
PDF
REST that won't make you cry
PPTX
Как договариваться с начальником и заказчиком: выбираем нужный протокол общения
PPTX
Обзор программы SAP HANA Startup Focus
PPTX
World of Agile: Kanban
PPTX
Risk Management
PPTX
«Spring Integration as Integration Patterns Provider»
PPTX
Cutting edge of Machine Learning
PPTX
Parallel Programming In Modern World .NET Technics
PPTX
Parallel programming in modern world .net technics shared
PPTX
Maximize Effectiveness of Human Capital
Quality attributes testing. From Architecture to test acceptance
Mobile development for JavaScript developer
Building an Innovation & Strategy Process
IT Professionals – The Right Time/The Right Place
Building a Data Driven Organization
7 Tools for the Product Owner
Hacking your Doorbell
An era of possibilities, a window in time
Web services automation from sketch
Why Ruby?
REST that won't make you cry
Как договариваться с начальником и заказчиком: выбираем нужный протокол общения
Обзор программы SAP HANA Startup Focus
World of Agile: Kanban
Risk Management
«Spring Integration as Integration Patterns Provider»
Cutting edge of Machine Learning
Parallel Programming In Modern World .NET Technics
Parallel programming in modern world .net technics shared
Maximize Effectiveness of Human Capital

Smarter Testing With Spock

  • 1. Smarter Testing With Spock Dmitry Voloshko 03/11/2012
  • 2. What we’ll talk about Spock?! State Based Testing Data Driven Testing Interaction Based Testing Spock Extensions More Cool Stuff
  • 4. Spock is... A developer testing framework... for Groovy and Java applications... based on Groovy... fully compatible with JUnit... but going beyond!
  • 5. Spock Can... Reduce the lines of test code Make tests more readable Turn tests into specifications Be extended in powerful ways Bring back the fun to testing!
  • 6. Getting Started Homepage http://spockframework.org Source Code https://github.com/spockframework/spock Spock Web Console http://meet.spockframework.org Spock Example Project http://downloads.spockframework.org https://github.com/spockframework/spock/tree/groovy-1.8/spock- example
  • 7. Who’s Using Spock? Gradle GPars Grails Geb Grails Plugin Collective Apache Tapestry Griffon Spock Spring?
  • 8. Who’s Using Spock? Betfair be2 bemoko BSkyB CTI Digital Donewtech Solutions eHarmony Energized Work Gennemtænkt IT IntelliGrape Software Netflix Smarter Ecommerce STERMEDIA Sp. z o.o. Software Projects Spot Diving SystemsForge TouK
  • 10. State Based Testing Classical Unit Testing Arrange Act Assert Given-When-Then
  • 11. The Code For Testing Account.java public class Account { private BigDecimal balance = new BigDecimal(0); public Account(BigDecimal initial) { balance = initial; } public BigDecimal getBalance() { return balance; } public void withdraw(BigDecimal amount) { if (amount.compareTo(BigDecimal.ZERO) < 0) { throw new NegativeAmountWithdrawnException(amount); } balance = balance.subtract(amount); } }
  • 12. The Code For Testing NegativeAmountWithdrawnException.java public class NegativeAmountWithdrawnException extends RuntimeException { private final BigDecimal amount; public NegativeAmountWithdrawnException(BigDecimal amount) { super("cannot withdraw" + amount); this.amount = amount; } public BigDecimal getAmount() { return amount; } }
  • 13. Show me the code public class AccountTest { @Test public void withdrawSomeAmount() { // given Account account = new Account(BigDecimal.valueOf(5)); // when account.withdraw(BigDecimal.valueOf(2)); // then assertEquals(BigDecimal.valueOf(3), account.getBalance()); } }
  • 14. Show me the code class AccountSpec extends Specification { def "withdraw some amount"() { given: Account account = new Account(BigDecimal.valueOf(5)); when: account.withdraw(BigDecimal.valueOf(2)); then: account.getBalance() == BigDecimal.valueOf(3); } }
  • 15. Show me the code class AccountSpec2 extends Specification { def "withdraw some amount"() { given: def account = new Account(5.0) when: account.withdraw(2.0) then: account.balance == 3.0 } }
  • 16. Show me the code class AccountSpec3 extends Specification { def "withdraw some amount"() { given: "an account with a balance of five euros" def account = new Account(5.0) when: "two euros are withdrawn" account.withdraw(2.0) then: "three euros remain in the account" account.balance == 3.0 } }
  • 17. Show me the code class AccountSpec4 extends Specification { def "can't withdraw a negative amount"() { given: def account = new Account(5.0) when: account.withdraw(-1.0) then: NegativeAmountWithdrawnException e = thrown() e.amount == -1.0 } def "withdrawing some amount decreases the balance by exactly that amount"() { def account = new Account(5.0) when: account.withdraw(2.0) then: account.balance == old(account.balance) - 2.0 } }
  • 18. Show me the code class SharedField extends Specification { @Shared File file def "a file based test"() { when: file = new File("foo.txt") file.createNewFile() then: file.exists() } def "by now the object is not null"() { expect: file.exists() cleanup: file.delete() } }
  • 19. Show me the code class SetupSpecSpec extends Specification { File file def setup() { file = new File("foo2.txt") } def "a file based test"() { when: file.createNewFile() then: file.exists() } def "by now the object is not null"() { expect: file.exists() cleanup: file.delete() } }
  • 20. Show me the code class Conditions extends Specification { def "when-then style"() { when: def x = Math.max(5, 9) then: x == 9 } def "expect style"() { expect: Math.max(5, 9) == 9 } def "more complex conditions"() { expect: germanCarBrands.any { it.size() >= 3 } } private getGermanCarBrands() { ["audi", "bmw", "porsche"] } }
  • 21. Recap: State Based Testing Blocks setup: cleanup: expect: given: when: then: where: and: Fixture Methods setup() cleanup() setupSpec() cleanupSpec() Instance and @Shared fields old() and thrown()
  • 23. Data Driven Testing Test the same behavior... with varying data!
  • 24. Show me the code class AccountSpecDataDriven extends Specification { @Unroll def "withdraw some amount"() { given: def account = new Account(balance) when: account.withdraw(withdrawn) then: account.balance == remaining where: balance | withdrawn | |remaining 5.0 | 2.0 | | 3.0 4.0 | 0.0 | | 4.0 4.0 | 4.0 | | 0.0 } }
  • 25. Show me the code class AccountSpecDataDriven extends Specification { @Unroll def "withdrawing #withdrawn from account with balance #balance"() { given: def account = new Account(balance) when: account.withdraw(withdrawn) then: account.balance == old(account.balance) – withdrawn where: balance | withdrawn 5.0 | 2.0 4.0 | 0.0 4.0 | 4.0 } }
  • 26. Show me the code class AccountSpecDatabaseDriven extends Specification { @Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver") def setupSpec() { sql.execute("create table accountdata (id int primary key, balance decimal, withdrawn decimal, remaining decimal)") sql.execute("insert into accountdata values (1, 5.0, 2.0, 3.0), (2, 4.0, 0.0, 4.0), (3, 4.0, 4.0, 0.0)") } @Unroll def "withdrawing #withdrawn from account with balance #balance leaves #remaining"() { given: def account = new Account(balance) when: account.withdraw(withdrawn) then: account.balance == remaining where: [balance, withdrawn, remaining] << sql.rows("select balance, withdrawn, remaining from accountdata") } }
  • 27. Recap: Data Driven Testing where: block Data tables External data sources @Unroll
  • 29. Interaction Based Testing Design and test how your objects communicate Mocking frameworks to the rescue Spock comes with its own mocking framework
  • 30. The Code For Testing PublisherSubscriber.groovy interface Subscriber { void receive(String message) } class Publisher { List<Subscriber> subscribers = [] void publish(String message) { for (subscriber in subscribers) { try { subscriber.receive(message) } catch (ignored) {} } } }
  • 31. The Code For Testing PublisherSubscriber.groovy interface Subscriber2 { void receive(String message) boolean isActive() } class Publisher2 { List<Subscriber2> subscribers = [] void publish(String message) { for (subscriber in subscribers) { try { if (subscriber.active) { subscriber.receive(message) } } catch (ignored) {} } } }
  • 32. Show me the code class PublisherSubscriberSpec extends Specification { def pub = new Publisher() def sub1 = Mock(Subscriber) def sub2 = Mock(Subscriber) def setup() { pub.subscribers << sub2 << sub1 } def "delivers messages to all subscribers"() { when: pub.publish("msg") then: 1 * sub1.receive("msg") 1 * sub2.receive("msg") } }
  • 33. Show me the code class PublisherSubscriberSpec2 extends Specification { def pub = new Publisher() def sub1 = Mock(Subscriber) def setup() { pub.subscribers << sub1 } def "delivers messages in the order they are published"() { when: pub.publish("msg1") pub.publish("msg2") then: 1 * sub1.receive("msg1") then: 1 * sub1.receive("msg2") } }
  • 34. Show me the code class PublisherSubscriber2Spec extends Specification { def pub = new Publisher2() def sub1 = Mock(Subscriber2) def sub2 = Mock(Subscriber2) def setup() { pub.subscribers << sub1 << sub2 } def "delivers messages to all active subscribers"() { sub1.active >> true sub2.active >> false when: pub.publish("msg") then: 1 * sub1.receive("msg") 0 * sub2.receive(_) } }
  • 35. Recap: Interaction Based Testing Creating def sub = Mock(Subscriber) Subscriber sub = Mock() Mocking 1 * sub.receive("msg") (1..3) * sub.receive(_) (1.._) * sub.receive(_ as String) 1 * sub.receive(!null) 1 * sub.receive({it.contains("m")}) 1 * _./rec.*/("msg")
  • 36. Recap: Interaction Based Testing Stubbing // now returns status code String receive(String msg) { ... } sub.receive(_) >> "ok" sub.receive(_) >>> ["ok", "ok", "fail"] sub.receive(_) >>> { msg -> msg.size() > 3 ? "ok" : "fail" } Mocking and Stubbing 3 * sub.receive(_) >>> ["ok", "ok", "fail"] Impressing your friends (_.._) * _._(*_) >> _
  • 40. Show me the code class JUnitRules extends Specification { @Rule TemporaryFolder tempFolder @Shared File file def "a file based test"() { when: file = tempFolder.newFile("foo.txt") then: file.exists() } def "by now the file has been deleted"() { expect: !file.exists() } }
  • 41. Show me the code @Stepwise class StepwiseSpec extends Specification { def "step 1"() { expect: true } def "step 2"() { expect: true } def "step 3"() { expect: true } }
  • 44. Grails Extensions @TestFor(MouthService) @Mock([Patient, PatientMouth, PatientTooth]) class MouthServiceSpec extends Specification { def "Get patient tooth by index"() { setup: "Create domain mocks" def patient = new Patient(dateOfBirth: new Date('05/03/1984')).save(false) def patientTooth = new PatientTooth(index: 10, toothCode: "10").save(false) def patientMouth = new PatientMouth(patient: patient, patientTeeth: [patientTooth]).save(false) when: patientTooth = service.getPatientToothByIndex(patientMouth, index) then: patientTooth.toothCode == tooth patientMouth.patientTeeth.contains(patientTooth) where: index | tooth 10 | "10" 20 | null } }
  • 45. Spring Extension class InjectionExamples extends Specification { @Autowired Service1 byType @Resource Service1 byName @Autowired ApplicationContext context }
  • 47. Configuring Spock ~/.spock/SpockConfig.groovy, or on class path, or with -Dspock.configuration runner { filterStackTrace false include Fast exclude Slow optimizeRunOrder true } @Fast class MyFastSpec extends Specification { def "I’m fast as hell!"() { expect: true } @Slow def “Sorry, can’t keep up..."() {expect: false } }
  • 48. Tooling Eclipse, IDEA Ant, Maven, Gradle Jenkins, Bamboo, TeamCity Spock runs everywhere JUnit and Groovy run!
  • 49. Spock Under The Hood You write... a = 1; b = 2; c = 4 expect: sum(a, b) == c Spock generates... def rec = new ValueRecorder() verifier.expect( rec.record(rec.record(sum(rec.record(a), rec.record(b)) == rec.record(c))) You see... sum (a, b) == c | | | | | 3 12 | 4 false
  • 50. Q&A Homepage http://spockframework.org Source Code https://github.com/spockframework/spock Spock Web Console http://meet.spockframework.org Spock Example Project http://downloads.spockframework.org https://github.com/spockframework/spock/tree/groovy-1.8/spock-example