SlideShare uma empresa Scribd logo
1 de 70
Baixar para ler offline
Spock
Spock
the enterprise ready specification framework
Ted Vinke, 2018
http://spockframework.org/spock/docs/1.1/index.html
• Overview

• Data Driven Testing

• Interaction Based Testing

• Extensions
class MathSpec extends Specification {
void "should find maximum of two numbers"() {
when:
def x = Math.max(1, 2)
then:
x == 2
}
}
class MathSpec extends Specification {
void "should find maximum of two numbers"() {
when:
def x = Math.max(1, 2)
then:
x == 2
}
}
class MathSpec extends Specification {
void "should find maximum of two numbers"() {
when:
def x = Math.max(1, 2)
then:
x == 2
}
}
class MathSpec extends Specification {
void "should find maximum of two numbers"() {
when:
def x = Math.max(1, 2)
then:
x == 2
}
}
setup:

when:

then:

expect:

cleanup:

where:
Setup

Stimulus

Response

Cleanup
Blocks Phases
setup:
def stack = new Stack()
def elem = "push me"
Setup Blocks
when:
stack.push(elem)
then:
!stack.empty
stack.size() == 1
stack.peek() == elem
Plain boolean conditions
Conditions
when:
stack.push(elem)
then:
!stack.empty
stack.size() == 2
stack.peek() == elem
Plain boolean conditions
Conditions
Condition not satisfied:
stack.size() == 2
| | |
| 1 false
[push me]
when:
stack.pop()
then:
thrown(EmptyStackException)
Exception conditions
Conditions
when:
stack.pop()
then:
def e = thrown(EmptyStackException)
Exception conditions
Conditions
when:
stack.pop()
then:
def e = thrown(EmptyStackException)
e.cause == null
Exception conditions
Conditions
when:
def x = Math.max(1, 2)
then:
x == 2
Expect Blocks
expect:
Math.max(1, 2) == 2
setup:
def file = new File("/some/path")
file.createNewFile()
// ...
cleanup:
file.delete()
Cleanup Blocks
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(1, 3) == 3
Math.max(7, 4) == 7
Math.max(0, 0) == 0
}
}
The naive way
Data Driven Testing
• Code and data are mixed and cannot
easily be changed independently

• Data cannot easily be auto-generated or
fetched from external sources

• In order to exercise the same code
multiple times, it either has to be
duplicated or extracted into a separate
method

• In case of a failure, it may not be
immediately clear which inputs caused
the failure

• Exercising the same code multiple times
does not benefit from the same isolation
as executing separate methods does
…has potential drawbacks:
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(1, 3) == 3
Math.max(7, 4) == 7
Math.max(0, 0) == 0
}
}
Refactored
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
}
}
Refactored
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
}
}
Refactored
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
...
}
}
Refactored
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
}
}
Data Tables
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0
}
}
Data Tables
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0
}
}
Data Tables
Data Driven Testing
method parameters omitted
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 7
0 | 0 || 0
}
}
Data Tables
Data Driven Testing
visually seperate inputs and outputs
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 7
0 | 0 || 0
}
}
Data Tables with visually seperated inputs and outputs
Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 7
0 | 0 || 0
}
}
Reporting of failures
Data Driven Testing
maximum of two numbers FAILED
Condition not satisfied:
Math.max(a, b) == c
| | | | |
| 7 4 | 7
42 false
@Unroll
def "maximum of two numbers"()
Reporting of failures
Data Driven Testing
maximum of two numbers[0] PASSED
maximum of two numbers[1] FAILED
Math.max(a, b) == c
| | | | |
| 7 4 | 7
42 false
maximum of two numbers[2] PASSED
@Unroll
def "maximum of #a and #b is #c"()
Reporting of failures
Data Driven Testing
maximum of 3 and 5 is 5 PASSED
maximum of 7 and 4 is 7 FAILED
Math.max(a, b) == c
| | | | |
| 7 4 | 7
42 false
maximum of 0 and 0 is 0 PASSED
...
where:
a << [1, 7, 0]
b << [3, 4, 0]
c << [3, 7, 0]
Data pipes
Data Driven Testing
...
where:
a = 3
b = Math.random() * 100
c = a > b ? a : b
@Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
[a, b, c] << sql.rows("select a, b, c from maxdata")
}
Data pipes
Data Driven Testing
Interaction Based
Testing
interface Subscriber {
void receive(String message)
}
Publishers and subscribers
Interaction Based Testing
class Publisher {
List<Subscriber> subscribers = []
int messageCount = 0
void send(String message){
subscribers*.receive(message)
messageCount++
}
}
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
}
Publishers and subscribers
Interaction Based Testing
class Publisher {
List<Subscriber> subscribers = []
int messageCount = 0
void send(String message){
subscribers*.receive(message)
messageCount++
}
}
interface Subscriber {
void receive(String message)
}
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
}
}
Publishers and subscribers
Interaction Based Testing
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
Subscriber subscriber = Mock()
Subscriber subscriber2 = Mock()
}
}
Creating mocks
Interaction Based Testing
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
Subscriber subscriber = Mock()
Subscriber subscriber2 = Mock()
def setup() {
// << is a Groovy shorthand for List.add()
publisher.subscribers << subscriber
publisher.subscribers << subscriber2
}}
}
Injecting mocks
Interaction Based Testing
def "should send messages to all subscribers"() {
}
Mocking
Interaction Based Testing
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
}
Mocking
Interaction Based Testing
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello")
1 * subscriber2.receive("hello")
}
Mocking
Interaction Based Testing
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello")
1 * subscriber2.receive("hello")
}
Mocking
Interaction Based Testing
interactions
1 * subscriber.receive("hello")
| | | |
| | | argument constraint
| | method constraint
| target constraint
cardinality
Interactions
Interaction Based Testing
1 * subscriber.receive("hello") // exactly one call
0 * subscriber.receive("hello") // zero calls
(1..3) * subscriber.receive("hello") // between one and three calls
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
_ * subscriber.receive("hello") // any number of calls
Cardinality
Interaction Based Testing
1 * subscriber.receive("hello") // exactly one call
0 * subscriber.receive("hello") // zero calls
(1..3) * subscriber.receive("hello") // between one and three calls
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
_ * subscriber.receive("hello") // any number of calls
Cardinality
Interaction Based Testing
1 * subscriber.receive("hello") // a call to 'subscriber'
1 * _.receive("hello") // a call to any mock object
Target Constraint
Interaction Based Testing
1 * subscriber.receive("hello") // a method named 'receive'
1 * subscriber./r.*e/("hello") // matches regular expression
Method Constraint
Interaction Based Testing
1 * subscriber.receive("hello") // an argument equal to the String "hello"
1 * subscriber.receive(!"hello") // an argument unequal to the String "hello"
1 * subscriber.receive() // the empty argument list
1 * subscriber.receive(_) // any single argument (including null)
1 * subscriber.receive(*_) // any argument list (including empty)
1 * subscriber.receive(!null) // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies predicate
Argument Constraints
Interaction Based Testing
1 * subscriber.receive("hello") // an argument equal to the String "hello"
1 * subscriber.receive(!"hello") // an argument unequal to the String "hello"
1 * subscriber.receive() // the empty argument list
1 * subscriber.receive(_) // any single argument (including null)
1 * subscriber.receive(*_) // any argument list (including empty)
1 * subscriber.receive(!null) // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies predicate
Argument Constraints
Interaction Based Testing
1 * process.invoke("ls", "-a", _, !null,
{ ["abcdefghiklmnopqrstuwx1"].contains(it) })
1 * subscriber._(*_)
Quiz Based Testing
1 * _
class MySpec extends Specification {
Subscriber subscriber = Mock
def setup() {
1 * subscriber.receive("hello")
1 * subscriber.receive("goodbye")
}
def "test"() {
}
}
Interactions everywhere!
class MySpec extends Specification {
Subscriber subscriber = Mock {
1 * receive("hello")
1 * receive("goodbye")
}
def "test"() {
}
}
class MySpec extends Specification {
Subscriber subscriber = Mock
def "test"() {
with(subscriber) {
1 * receive("hello")
1 * receive("goodbye")
}
}
}
when:
publisher.send("message1")
then:
1 * subscriber.receive("message1")
when:
publisher.send("message2")
then:
1 * subscriber.receive("message2")
Scope of Interactions
Interaction Based Testing
Verification of Interactions
Interaction Based Testing
Too many invocations for:
2 * subscriber.receive(_) (3 invocations)
Matching invocations (ordered by last occurrence):
2 * subscriber.receive("hello") <-- this triggered the error
1 * subscriber.receive("goodbye")
Verification of Interactions
Interaction Based Testing
Too few invocations for:
1 * subscriber.receive("hello") (0 invocations)
Unmatched invocations (ordered by similarity):
1 * subscriber.receive("goodbye")
1 * subscriber2.receive("hello")
Stubbing of interactions
Interaction Based Testing
interface Subscriber {
String receive(String message)
}
subscriber.receive(_) >> "ok"
subscriber.receive(_) >> "ok"
| | | |
| | | response generator
| | argument constraint
| method constraint
target constraint
Response generator
Interaction Based Testing
subscriber.receive(_) >> "ok"
Returning values
Interaction Based Testing
subscriber.receive("message1") >> "ok"
subscriber.receive("message2") >> "fail"
subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
subscriber.receive(_) >> { String message ->
message.size() > 3 ? "ok" : "fail" }
def subscriber = Stub(Subscriber)
Other kinds of mock objects
Interaction Based Testing
Stubs
Spies
def subscriber = Spy(SubscriberImpl, constructorArgs: ["Fred"])
Extensions
@Ignore
def "my feature"() { ... }
@IgnoreIf({ System.getProperty("os.name").contains("windows") })
def "my feature"() { ... }
@Requires({ os.windows })
class MySpec extends Specification { ... }
Ignoring and requiring
Extensions
@PendingFeature
def "not implemented yet"() { ... }
Pending features
Extensions
@Timeout(5)
def "I fail if I run for more than five seconds"() { ... }
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
def "I better be quick" { ... }
Timeouts
Extensions
@Narrative("""
As a user
I want foo
So that bar
""")
@See("http://spockframework.org/spec")
class MySpec {
@Issue("http://my.issues.org/FOO-2")
def "Foo should do bar"() { ... }
}
Documentation
Extensions
def "should send emails to matching users"() {
given:
def user1 = new User(id: 1L, userName: 'user one', email: 'test@user.one')
def user2 = new User(id: 2L, userName: 'user two', email: ‘test@user.two')
def user3 = new User(id: 3L, userName: 'THIRD test user', email: 'test@user.three')
def user4 = new User(id: 4L, userName: 'testing user four', email: 'test@user.four')
def subject = 'some test email subject'
def content = 'some content of the email'
when:
def result = underTest.sendEmailsToUsers(subject, content, 'test')
then: "get users from repository and send email to each matching user"
1 * userRepository.findAll() >> [user1, user2, user3, user4]
1 * emailSender.sendEmail(subject, content, 'test@user.one')
1 * emailSender.sendEmail(subject, content, 'test@user.four')
result == ['test@user.one', 'test@user.four']
}
@Test
public void testSendingEmailsToMatchingUsers() {
//given:
User user1 = new User();
user1.setId(1L);
user1.setUserName("test user one");
user1.setEmail("test@user.one");
User user2 = new User();
user2.setId(2L);
user2.setUserName("test user two");
user2.setEmail("test@user.two");
User user3 = new User();
user3.setId(3L);
user3.setUserName("THIRD test user");
user3.setEmail("test@user.three");
User user4 = new User();
user4.setId(4L);
user4.setUserName("testing user four");
user4.setEmail("test@user.four");
String subject = "some test email subject";
String content = "some content of the email";
when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2, user3, user4));
//when:
List<String> result = underTest.sendEmailsToUsers(subject, content, "test");
//then:
Assert.assertEquals(Arrays.asList("test@user.one", "test@user.four"), result);
verify(userRepository).findAll();
}
Mockito vs Spock
http://spockframework.org/spock/docs/1.1/index.html
Spock
Thank you.

Mais conteúdo relacionado

Mais procurados

Java script objects 1
Java script objects 1Java script objects 1
Java script objects 1
H K
 
Data Analysis and Programming in R
Data Analysis and Programming in RData Analysis and Programming in R
Data Analysis and Programming in R
Eshwar Sai
 
Indexing and Query Optimizer (Aaron Staple)
Indexing and Query Optimizer (Aaron Staple)Indexing and Query Optimizer (Aaron Staple)
Indexing and Query Optimizer (Aaron Staple)
MongoSF
 

Mais procurados (19)

C# p9
C# p9C# p9
C# p9
 
Fp java8
Fp java8Fp java8
Fp java8
 
Extractors & Implicit conversions
Extractors & Implicit conversionsExtractors & Implicit conversions
Extractors & Implicit conversions
 
Java script objects 1
Java script objects 1Java script objects 1
Java script objects 1
 
Java_practical_handbook
Java_practical_handbookJava_practical_handbook
Java_practical_handbook
 
Java 104
Java 104Java 104
Java 104
 
Python dictionary : past, present, future
Python dictionary: past, present, futurePython dictionary: past, present, future
Python dictionary : past, present, future
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
How to Become a Tree Hugger: Random Forests and Predictive Modeling for Devel...
 
Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...
Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...
Analysis of Fatal Utah Avalanches with Python. From Scraping, Analysis, to In...
 
Data Analysis and Programming in R
Data Analysis and Programming in RData Analysis and Programming in R
Data Analysis and Programming in R
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
Java script arrays
Java script arraysJava script arrays
Java script arrays
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
 
Final JAVA Practical of BCA SEM-5.
Final JAVA Practical of BCA SEM-5.Final JAVA Practical of BCA SEM-5.
Final JAVA Practical of BCA SEM-5.
 
Indexing and Query Optimizer (Aaron Staple)
Indexing and Query Optimizer (Aaron Staple)Indexing and Query Optimizer (Aaron Staple)
Indexing and Query Optimizer (Aaron Staple)
 
Java PRACTICAL file
Java PRACTICAL fileJava PRACTICAL file
Java PRACTICAL file
 
18. Java associative arrays
18. Java associative arrays18. Java associative arrays
18. Java associative arrays
 
The Tools for Data Migration Between Oracle , MySQL and Flat Text File.
The Tools for Data Migration Between Oracle , MySQL and Flat Text File.The Tools for Data Migration Between Oracle , MySQL and Flat Text File.
The Tools for Data Migration Between Oracle , MySQL and Flat Text File.
 

Semelhante a Spock the enterprise ready specifiation framework - Ted Vinke

LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
ShashikantSathe3
 
Lecture 5: Functional Programming
Lecture 5: Functional ProgrammingLecture 5: Functional Programming
Lecture 5: Functional Programming
Eelco Visser
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0
tutorialsruby
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0
tutorialsruby
 
PowerShell_LangRef_v3 (1).pdf
PowerShell_LangRef_v3 (1).pdfPowerShell_LangRef_v3 (1).pdf
PowerShell_LangRef_v3 (1).pdf
outcast96
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 

Semelhante a Spock the enterprise ready specifiation framework - Ted Vinke (20)

Smarter Testing With Spock
Smarter Testing With SpockSmarter Testing With Spock
Smarter Testing With Spock
 
Specs2
Specs2Specs2
Specs2
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
 
Javascript math boolean string date
Javascript math boolean string dateJavascript math boolean string date
Javascript math boolean string date
 
Lecture 5: Functional Programming
Lecture 5: Functional ProgrammingLecture 5: Functional Programming
Lecture 5: Functional Programming
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
 
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykMock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0
 
RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0RubyMiniGuide-v1.0_0
RubyMiniGuide-v1.0_0
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
Spsl vi unit final
Spsl vi unit finalSpsl vi unit final
Spsl vi unit final
 
Spsl v unit - final
Spsl v unit - finalSpsl v unit - final
Spsl v unit - final
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 
Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
 
PowerShell_LangRef_v3 (1).pdf
PowerShell_LangRef_v3 (1).pdfPowerShell_LangRef_v3 (1).pdf
PowerShell_LangRef_v3 (1).pdf
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 

Mais de Ted Vinke

Mais de Ted Vinke (11)

Upcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool TimeUpcoming Events 2017 for a Java Software Developer - Ted's Tool Time
Upcoming Events 2017 for a Java Software Developer - Ted's Tool Time
 
Gmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool TimeGmail Email Markup - Ted's Tool Time
Gmail Email Markup - Ted's Tool Time
 
Specifications pattern - Ted's Tool Time
Specifications pattern - Ted's Tool TimeSpecifications pattern - Ted's Tool Time
Specifications pattern - Ted's Tool Time
 
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool TimeCode Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
Code Generation with Groovy, Lombok, AutoValue and Immutables - Ted's Tool Time
 
JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool TimeJUnit 5 - The Next Generation of JUnit - Ted's Tool Time
JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
 
JEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool TimeJEP 286 Local-Variable Type Inference - Ted's Tool Time
JEP 286 Local-Variable Type Inference - Ted's Tool Time
 
Devoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and DockerDevoxx 2015 - Web Application Development using Grails and Docker
Devoxx 2015 - Web Application Development using Grails and Docker
 
Working with Groovy Collections
Working with Groovy CollectionsWorking with Groovy Collections
Working with Groovy Collections
 
The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015The Apache Software Foundation - Ted's Tool Time - Sep 2015
The Apache Software Foundation - Ted's Tool Time - Sep 2015
 
Devoxx 2014 Report
Devoxx 2014 ReportDevoxx 2014 Report
Devoxx 2014 Report
 
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
 

Último

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
mbmh111980
 

Último (20)

how-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdfhow-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdf
 
How to pick right visual testing tool.pdf
How to pick right visual testing tool.pdfHow to pick right visual testing tool.pdf
How to pick right visual testing tool.pdf
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 
SQL Injection Introduction and Prevention
SQL Injection Introduction and PreventionSQL Injection Introduction and Prevention
SQL Injection Introduction and Prevention
 
The Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion ProductionThe Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion Production
 
IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024
 
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdfMicrosoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
Microsoft 365 Copilot; An AI tool changing the world of work _PDF.pdf
 
A Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data MigrationA Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data Migration
 
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
KLARNA -  Language Models and Knowledge Graphs: A Systems ApproachKLARNA -  Language Models and Knowledge Graphs: A Systems Approach
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
 
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
 
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdfImplementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
 
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdfA Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
 
OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024
 
10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf
 
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
 
AI Hackathon.pptx
AI                        Hackathon.pptxAI                        Hackathon.pptx
AI Hackathon.pptx
 

Spock the enterprise ready specifiation framework - Ted Vinke

  • 1. Spock Spock the enterprise ready specification framework Ted Vinke, 2018
  • 3. • Overview • Data Driven Testing • Interaction Based Testing • Extensions
  • 4.
  • 5.
  • 6.
  • 7. class MathSpec extends Specification { void "should find maximum of two numbers"() { when: def x = Math.max(1, 2) then: x == 2 } }
  • 8. class MathSpec extends Specification { void "should find maximum of two numbers"() { when: def x = Math.max(1, 2) then: x == 2 } }
  • 9. class MathSpec extends Specification { void "should find maximum of two numbers"() { when: def x = Math.max(1, 2) then: x == 2 } }
  • 10. class MathSpec extends Specification { void "should find maximum of two numbers"() { when: def x = Math.max(1, 2) then: x == 2 } }
  • 12. setup: def stack = new Stack() def elem = "push me" Setup Blocks
  • 14. when: stack.push(elem) then: !stack.empty stack.size() == 2 stack.peek() == elem Plain boolean conditions Conditions Condition not satisfied: stack.size() == 2 | | | | 1 false [push me]
  • 16. when: stack.pop() then: def e = thrown(EmptyStackException) Exception conditions Conditions
  • 17. when: stack.pop() then: def e = thrown(EmptyStackException) e.cause == null Exception conditions Conditions
  • 18. when: def x = Math.max(1, 2) then: x == 2 Expect Blocks expect: Math.max(1, 2) == 2
  • 19. setup: def file = new File("/some/path") file.createNewFile() // ... cleanup: file.delete() Cleanup Blocks
  • 21. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(1, 3) == 3 Math.max(7, 4) == 7 Math.max(0, 0) == 0 } } The naive way Data Driven Testing • Code and data are mixed and cannot easily be changed independently
 • Data cannot easily be auto-generated or fetched from external sources
 • In order to exercise the same code multiple times, it either has to be duplicated or extracted into a separate method
 • In case of a failure, it may not be immediately clear which inputs caused the failure
 • Exercising the same code multiple times does not benefit from the same isolation as executing separate methods does …has potential drawbacks:
  • 22. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(1, 3) == 3 Math.max(7, 4) == 7 Math.max(0, 0) == 0 } } Refactored Data Driven Testing
  • 23. class MathSpec extends Specification { def "maximum of two numbers"() { expect: } } Refactored Data Driven Testing
  • 24. class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: } } Refactored Data Driven Testing
  • 25. class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c ... } } Refactored Data Driven Testing
  • 26. class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c } } Data Tables Data Driven Testing
  • 27. class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c where: a | b | c 1 | 3 | 3 7 | 4 | 7 0 | 0 | 0 } } Data Tables Data Driven Testing
  • 28. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b | c 1 | 3 | 3 7 | 4 | 7 0 | 0 | 0 } } Data Tables Data Driven Testing method parameters omitted
  • 29. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c 1 | 3 || 3 7 | 4 || 7 0 | 0 || 0 } } Data Tables Data Driven Testing visually seperate inputs and outputs
  • 30. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c 1 | 3 || 3 7 | 4 || 7 0 | 0 || 0 } } Data Tables with visually seperated inputs and outputs Data Driven Testing
  • 31. class MathSpec extends Specification { def "maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b || c 1 | 3 || 3 7 | 4 || 7 0 | 0 || 0 } } Reporting of failures Data Driven Testing maximum of two numbers FAILED Condition not satisfied: Math.max(a, b) == c | | | | | | 7 4 | 7 42 false
  • 32. @Unroll def "maximum of two numbers"() Reporting of failures Data Driven Testing maximum of two numbers[0] PASSED maximum of two numbers[1] FAILED Math.max(a, b) == c | | | | | | 7 4 | 7 42 false maximum of two numbers[2] PASSED
  • 33. @Unroll def "maximum of #a and #b is #c"() Reporting of failures Data Driven Testing maximum of 3 and 5 is 5 PASSED maximum of 7 and 4 is 7 FAILED Math.max(a, b) == c | | | | | | 7 4 | 7 42 false maximum of 0 and 0 is 0 PASSED
  • 34. ... where: a << [1, 7, 0] b << [3, 4, 0] c << [3, 7, 0] Data pipes Data Driven Testing ... where: a = 3 b = Math.random() * 100 c = a > b ? a : b
  • 35. @Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver") def "maximum of two numbers"() { expect: Math.max(a, b) == c where: [a, b, c] << sql.rows("select a, b, c from maxdata") } Data pipes Data Driven Testing
  • 37. interface Subscriber { void receive(String message) } Publishers and subscribers Interaction Based Testing class Publisher { List<Subscriber> subscribers = [] int messageCount = 0 void send(String message){ subscribers*.receive(message) messageCount++ } }
  • 38. class PublisherSpec extends Specification { Publisher publisher = new Publisher() } Publishers and subscribers Interaction Based Testing class Publisher { List<Subscriber> subscribers = [] int messageCount = 0 void send(String message){ subscribers*.receive(message) messageCount++ } } interface Subscriber { void receive(String message) }
  • 39.
  • 40. class PublisherSpec extends Specification { Publisher publisher = new Publisher() } } Publishers and subscribers Interaction Based Testing
  • 41. class PublisherSpec extends Specification { Publisher publisher = new Publisher() Subscriber subscriber = Mock() Subscriber subscriber2 = Mock() } } Creating mocks Interaction Based Testing
  • 42. class PublisherSpec extends Specification { Publisher publisher = new Publisher() Subscriber subscriber = Mock() Subscriber subscriber2 = Mock() def setup() { // << is a Groovy shorthand for List.add() publisher.subscribers << subscriber publisher.subscribers << subscriber2 }} } Injecting mocks Interaction Based Testing
  • 43. def "should send messages to all subscribers"() { } Mocking Interaction Based Testing
  • 44. def "should send messages to all subscribers"() { when: publisher.send("hello") } Mocking Interaction Based Testing
  • 45. def "should send messages to all subscribers"() { when: publisher.send("hello") then: 1 * subscriber.receive("hello") 1 * subscriber2.receive("hello") } Mocking Interaction Based Testing
  • 46. def "should send messages to all subscribers"() { when: publisher.send("hello") then: 1 * subscriber.receive("hello") 1 * subscriber2.receive("hello") } Mocking Interaction Based Testing interactions
  • 47. 1 * subscriber.receive("hello") | | | | | | | argument constraint | | method constraint | target constraint cardinality Interactions Interaction Based Testing
  • 48. 1 * subscriber.receive("hello") // exactly one call 0 * subscriber.receive("hello") // zero calls (1..3) * subscriber.receive("hello") // between one and three calls (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls _ * subscriber.receive("hello") // any number of calls Cardinality Interaction Based Testing
  • 49. 1 * subscriber.receive("hello") // exactly one call 0 * subscriber.receive("hello") // zero calls (1..3) * subscriber.receive("hello") // between one and three calls (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls _ * subscriber.receive("hello") // any number of calls Cardinality Interaction Based Testing
  • 50. 1 * subscriber.receive("hello") // a call to 'subscriber' 1 * _.receive("hello") // a call to any mock object Target Constraint Interaction Based Testing
  • 51. 1 * subscriber.receive("hello") // a method named 'receive' 1 * subscriber./r.*e/("hello") // matches regular expression Method Constraint Interaction Based Testing
  • 52. 1 * subscriber.receive("hello") // an argument equal to the String "hello" 1 * subscriber.receive(!"hello") // an argument unequal to the String "hello" 1 * subscriber.receive() // the empty argument list 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (including empty) 1 * subscriber.receive(!null) // any non-null argument 1 * subscriber.receive(_ as String) // any non-null argument that is-a String 1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies predicate Argument Constraints Interaction Based Testing
  • 53. 1 * subscriber.receive("hello") // an argument equal to the String "hello" 1 * subscriber.receive(!"hello") // an argument unequal to the String "hello" 1 * subscriber.receive() // the empty argument list 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (including empty) 1 * subscriber.receive(!null) // any non-null argument 1 * subscriber.receive(_ as String) // any non-null argument that is-a String 1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies predicate Argument Constraints Interaction Based Testing 1 * process.invoke("ls", "-a", _, !null, { ["abcdefghiklmnopqrstuwx1"].contains(it) })
  • 54. 1 * subscriber._(*_) Quiz Based Testing 1 * _
  • 55. class MySpec extends Specification { Subscriber subscriber = Mock def setup() { 1 * subscriber.receive("hello") 1 * subscriber.receive("goodbye") } def "test"() { } } Interactions everywhere! class MySpec extends Specification { Subscriber subscriber = Mock { 1 * receive("hello") 1 * receive("goodbye") } def "test"() { } } class MySpec extends Specification { Subscriber subscriber = Mock def "test"() { with(subscriber) { 1 * receive("hello") 1 * receive("goodbye") } } }
  • 56. when: publisher.send("message1") then: 1 * subscriber.receive("message1") when: publisher.send("message2") then: 1 * subscriber.receive("message2") Scope of Interactions Interaction Based Testing
  • 57. Verification of Interactions Interaction Based Testing Too many invocations for: 2 * subscriber.receive(_) (3 invocations) Matching invocations (ordered by last occurrence): 2 * subscriber.receive("hello") <-- this triggered the error 1 * subscriber.receive("goodbye")
  • 58. Verification of Interactions Interaction Based Testing Too few invocations for: 1 * subscriber.receive("hello") (0 invocations) Unmatched invocations (ordered by similarity): 1 * subscriber.receive("goodbye") 1 * subscriber2.receive("hello")
  • 59. Stubbing of interactions Interaction Based Testing interface Subscriber { String receive(String message) } subscriber.receive(_) >> "ok"
  • 60. subscriber.receive(_) >> "ok" | | | | | | | response generator | | argument constraint | method constraint target constraint Response generator Interaction Based Testing
  • 61. subscriber.receive(_) >> "ok" Returning values Interaction Based Testing subscriber.receive("message1") >> "ok" subscriber.receive("message2") >> "fail" subscriber.receive(_) >>> ["ok", "error", "error", "ok"] subscriber.receive(_) >> { String message -> message.size() > 3 ? "ok" : "fail" }
  • 62. def subscriber = Stub(Subscriber) Other kinds of mock objects Interaction Based Testing Stubs Spies def subscriber = Spy(SubscriberImpl, constructorArgs: ["Fred"])
  • 64. @Ignore def "my feature"() { ... } @IgnoreIf({ System.getProperty("os.name").contains("windows") }) def "my feature"() { ... } @Requires({ os.windows }) class MySpec extends Specification { ... } Ignoring and requiring Extensions
  • 65. @PendingFeature def "not implemented yet"() { ... } Pending features Extensions
  • 66. @Timeout(5) def "I fail if I run for more than five seconds"() { ... } @Timeout(value = 100, unit = TimeUnit.MILLISECONDS) def "I better be quick" { ... } Timeouts Extensions
  • 67. @Narrative(""" As a user I want foo So that bar """) @See("http://spockframework.org/spec") class MySpec { @Issue("http://my.issues.org/FOO-2") def "Foo should do bar"() { ... } } Documentation Extensions
  • 68. def "should send emails to matching users"() { given: def user1 = new User(id: 1L, userName: 'user one', email: 'test@user.one') def user2 = new User(id: 2L, userName: 'user two', email: ‘test@user.two') def user3 = new User(id: 3L, userName: 'THIRD test user', email: 'test@user.three') def user4 = new User(id: 4L, userName: 'testing user four', email: 'test@user.four') def subject = 'some test email subject' def content = 'some content of the email' when: def result = underTest.sendEmailsToUsers(subject, content, 'test') then: "get users from repository and send email to each matching user" 1 * userRepository.findAll() >> [user1, user2, user3, user4] 1 * emailSender.sendEmail(subject, content, 'test@user.one') 1 * emailSender.sendEmail(subject, content, 'test@user.four') result == ['test@user.one', 'test@user.four'] } @Test public void testSendingEmailsToMatchingUsers() { //given: User user1 = new User(); user1.setId(1L); user1.setUserName("test user one"); user1.setEmail("test@user.one"); User user2 = new User(); user2.setId(2L); user2.setUserName("test user two"); user2.setEmail("test@user.two"); User user3 = new User(); user3.setId(3L); user3.setUserName("THIRD test user"); user3.setEmail("test@user.three"); User user4 = new User(); user4.setId(4L); user4.setUserName("testing user four"); user4.setEmail("test@user.four"); String subject = "some test email subject"; String content = "some content of the email"; when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2, user3, user4)); //when: List<String> result = underTest.sendEmailsToUsers(subject, content, "test"); //then: Assert.assertEquals(Arrays.asList("test@user.one", "test@user.four"), result); verify(userRepository).findAll(); } Mockito vs Spock