SlideShare a Scribd company logo
Dmitry Voloshko
Smarter Testing
With Spock
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 1 2 | 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 Testing Framework - The Next Generation
PDF
Spock Framework
PPTX
Smarter Testing With Spock
PDF
Spock framework
PPTX
Unit/Integration Testing using Spock
PDF
Spock: Test Well and Prosper
PDF
Spock: A Highly Logical Way To Test
PPT
Unit testing with Spock Framework
Spock Testing Framework - The Next Generation
Spock Framework
Smarter Testing With Spock
Spock framework
Unit/Integration Testing using Spock
Spock: Test Well and Prosper
Spock: A Highly Logical Way To Test
Unit testing with Spock Framework

What's hot (20)

PDF
Grails/Groovyによる開発事例紹介
PDF
PPT
PPTX
Unit Testing with Foq
PPTX
PDF
Advanced Java Practical File
PDF
DCN Practical
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
Core java pract_sem iii
PDF
Java 7 LavaJUG
PDF
Software Testing - Invited Lecture at UNSW Sydney
PDF
Introduction to web programming for java and c# programmers by @drpicox
DOCX
Java practical
KEY
DjangoCon US 2011 - Monkeying around at New Relic
PDF
Redux for ReactJS Programmers
PDF
Clojure - A new Lisp
DOC
Final JAVA Practical of BCA SEM-5.
PDF
The Ring programming language version 1.8 book - Part 9 of 202
KEY
Inside PyMongo - MongoNYC
PDF
ES3-2020-06 Test Driven Development (TDD)
Grails/Groovyによる開発事例紹介
Unit Testing with Foq
Advanced Java Practical File
DCN Practical
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Core java pract_sem iii
Java 7 LavaJUG
Software Testing - Invited Lecture at UNSW Sydney
Introduction to web programming for java and c# programmers by @drpicox
Java practical
DjangoCon US 2011 - Monkeying around at New Relic
Redux for ReactJS Programmers
Clojure - A new Lisp
Final JAVA Practical of BCA SEM-5.
The Ring programming language version 1.8 book - Part 9 of 202
Inside PyMongo - MongoNYC
ES3-2020-06 Test Driven Development (TDD)
Ad

Viewers also liked (10)

PPT
Spock Framework 2
PPT
Groovier testing with Spock
PPT
Testing Storm components with Groovy and Spock
PDF
Spring puzzlers
PPTX
Vert.x 세미나 이지원_배포용
PDF
A Gentle Introduction To Docker And All Things Containers
PDF
Docker by Example - Basics
PDF
Java Testing With Spock - Ken Sipe (Trexin Consulting)
PDF
UX, ethnography and possibilities: for Libraries, Museums and Archives
PDF
3 Things Every Sales Team Needs to Be Thinking About in 2017
Spock Framework 2
Groovier testing with Spock
Testing Storm components with Groovy and Spock
Spring puzzlers
Vert.x 세미나 이지원_배포용
A Gentle Introduction To Docker And All Things Containers
Docker by Example - Basics
Java Testing With Spock - Ken Sipe (Trexin Consulting)
UX, ethnography and possibilities: for Libraries, Museums and Archives
3 Things Every Sales Team Needs to Be Thinking About in 2017
Ad

Similar to Smarter Testing with Spock (20)

PPT
Play!ng with scala
PDF
Fun Teaching MongoDB New Tricks
KEY
Why ruby
PDF
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
PDF
Introduction to-mongo db-execution-plan-optimizer-final
PDF
Introduction to Mongodb execution plan and optimizer
PDF
A piece of sugar in your client-side development
PPTX
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
PDF
G*ワークショップ in 仙台 Grails(とことん)入門
PDF
Front End Development: The Important Parts
PPTX
More Data, More Problems: Evolving big data machine learning pipelines with S...
PDF
Scala coated JVM
PPTX
Rx for Android & iOS by Harin Trivedi
PDF
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
PDF
What's new in Python 3.11
KEY
What's New In Python 2.6
PDF
Building Apps with MongoDB
PDF
PDF
Exploring Clojurescript
PDF
ES3-2020-P3 TDD Calculator
Play!ng with scala
Fun Teaching MongoDB New Tricks
Why ruby
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
Introduction to-mongo db-execution-plan-optimizer-final
Introduction to Mongodb execution plan and optimizer
A piece of sugar in your client-side development
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
G*ワークショップ in 仙台 Grails(とことん)入門
Front End Development: The Important Parts
More Data, More Problems: Evolving big data machine learning pipelines with S...
Scala coated JVM
Rx for Android & iOS by Harin Trivedi
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
What's new in Python 3.11
What's New In Python 2.6
Building Apps with MongoDB
Exploring Clojurescript
ES3-2020-P3 TDD Calculator

Smarter Testing with Spock

  • 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 1 2 | 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