SlideShare a Scribd company logo
1 of 65
1 / 65
Spock Framework
Code Factory presentation, Jul, 2018
Stavila Leonid
2 / 65
Introduction
Many modern programming languages are
popular due to the libraries and frameworks that
are written on them. Where would Ruby be
without Rails?
3 / 65
The Java visiting card is primarily
Spring and Hibernate
4 / 65
Scala glorified the Akka framework
5 / 65
Groovy is primarily Gradle and Spock
6 / 65
Kotlin... To be honest, it seems to me that the
ratings of this language are artificially
overstated.
7 / 65
So, Spock
To begin with, this test framework is written in
Groovy.
For large projects, this language is not
recommended, like and Scala, but for small
scripts and tests it is very suitable.
8 / 65
Groovy
In fact, this language is a superset of Java, that
is, if you don’t know how to write-write in Java.
But knowledge of Groovy syntax can save you
time.
Groovy is a kind of script version of Java. It's
simpler, more compact, but at the same time
provides all the power of the JVM.
9 / 65
A classic example is
`hello world`
Java:
System.out.println("Hello world!");
Groovy:
println 'Hello world!'
10 / 65
Economy
println 'Hello world!'

The length of the method name

Two brackets

Quotes. Single quotes are easier to type

Semicolon
11 / 65
Reading data from a file:
BufferedReader br = new BufferedReader(new
FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
System.out.println("line = " + line);
}
} finally {
if (br != null) {
br.close();
}
}
12 / 65
This hulk can be placed
in one line
new File("file.txt")
.eachLine { println "line = $it" }
But most of all I like Groovy's ability to laconically
process collections.
Even revolutionary innovations in Java 8 do not
approach them.
13 / 65
Working with a collection

Java:
List<Integer> results =
Stream.of(1, 2, 3)
.map(v -> v * 2)
.collect(Collectors.toList());

Groovy:
List results = [1, 2, 3]
.collect { it * 2 }
14 / 65
Example of filtering

Java:
List<Integer> evenNumbers =
Stream.of(1, 2, 3, 4).filter(v -> v %
2 == 0).collect(Collectors.toList());

Groovy:
List evenNumbers = [1, 2, 3, 4]
.findAll { it % 2 == 0 }
15 / 65
Let's get back to testing
In the world of Java, JUnit rules in conjunction
with any of the available frameworks for
mocking (Mockito, EasyMock, PowerMock,
etc.).
This is enough to write a test of any complexity,
but this classic approach has drawbacks.
16 / 65

There is no way to give tests a normal and
understandable names. The names of
methods in the style of Camel Case are not
considered, and Junit 5 has not yet received
the proper distribution.
‘shouldAddToCartIfItemIsAvailaibleAndThe
LimitIsNotExceededAnd…..’.
17 / 65

Tests are overloaded with verbose constructs,
such as Collections.singletonList(),
Verify(…), any(MyAwesomeAbstract-
FactoryBaseClass.class) and so on.
18 / 65

Because these frameworks don’t allow a
normal way of dividing the testing process into
a configuration phase, testing itself and
checking the result, very often the tests look
just like a pile of incomprehensible, and
bizarrely mixed code.
19 / 65

In order to test incoming arguments, you need
to build cumbersome structures.
20 / 65

There is no normal support for parameterized
tests. As a result, to cover all cases, we need
to write many similar tests.
21 / 65
When the tests begin to bring a lot of pain, we
try not to use them, or we write trashy, and as a
result we then face even greater pain.
Bad tests don’t guarantee that any new code
change will not break anything else.
22 / 65
Tests written on Groovy look smoother, they are
easier to read and understand. But some
people did not think it was enough, and after a
while a group of enthusiasts wrote their test
framework, Spock.
23 / 65
Spock Framework
For many years, programmers have come to the
conclusion that the more code resembles the
usual sentences of the human language, the
easier and faster it can be understood.
24 / 65
In programming practice, this is not always
applicable. But in testing, due to the fact that all
tests are similar in their idea, this practice is
successfully used.
Programming languages that allow you to flexibly
change your syntax, were able to realize this idea
to the fullest extent.
25 / 65
Currently, tests can be started by customers
who are far from programming. All that is
needed is to write the business requirements in
a compact form. Next, programmers will simply
translate this test into code.
For example: "When the user press the start
button. then the menu is shown as in the
picture".
26 / 65
A simpler example
Addition of numbers 2 and 2 must return 4
This short formulation can already be used as a
test name. It remains only to describe his body.
As in any other test, we have the initial data,
the operation that we need to test and check
the result.
27 / 65
This can be described in three words:
given, when, then:
Addition of numbers 2 and 2 must return 4

given: 2, 2

when: 2 + 2

then: 4
This approach is called BDD (Behavior Driven
Development).
28 / 65
Spock is a modern framework for testing. It's
written in Groovy, includes tools for stubbing
and mocking and embodies the idea of BDD. In
fact, this is a domain specific language (DSL),
created specifically for writing tests.
It is an extension of the Junit runner and you do
not have to change anything in the
infrastructure to run these tests.
29 / 65
Advantages

Groovy is not as verbose as Java

The special syntax is aimed specifically at testing

Built-in support for Stubs and Mocks

Extends Junit runner

Simple testing with parameters

Keywords for all testing phases (given, when, then …)

Ease of describing methods

Many other specific features
30 / 65
Basics
31 / 65
Specification Template
class MyFirstSpecification extends Specification {
// fields
// fixture methods
// feature methods
// helper methods
}
32 / 65
Fixture Methods
Run before every feature method:
def setup() {}
Run after every feature method:
def cleanup() {}
Run before the first feature method:
def setupSpec() {}
Run after the last feature method:
33 / 65
Blocks Order

given: data initialization goes here (includes
creating mocks)

when: invoke your test subject here and assign it
to a variable

then: assert data here

cleanup: optional

where: optional: provide parameterized data
(tables or pipes)
34 / 65
Or

given

expect: combines when with then

cleanup

where
35 / 65
Junit comparison
Spock JUnit
Specification Test class
setup() @Before
cleanup() @After
setupSpec() @BeforeClass
cleanupSpec() @AfterClass
Feature Test
Feature method Test method
Data-driven feature Theory
Condition Assertion
Exception condition @Test(expected=…)​
Interaction Mock expectation (e.g. in Mockito)
36 / 65
Data Driven Testing
37 / 65
Data Tables
class Math 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 // passes
7 | 4 || 4 // fails
0 | 0 || 0 // passes
38 / 65
Unrolling
A method annotated with @Unroll will have its
rows from data table reported independently:
@Unroll
def "maximum of two numbers"() { ... }
39 / 65
Result with Unroll
maximum of two numbers[0] PASSED
maximum of two numbers[1] FAILED
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
40 / 65
Result Without Unroll
We have to figure out which row failed manually
maximum of two numbers FAILED
Condition not satisfied:
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
41 / 65
Data Pipes
Right side must be Collection, String or Iterable.
where:
a << [3, 7, 0]
b << [5, 0, 0]
c << [5, 7, 0]
42 / 65
Multi-Variable Data Pipes
where:
[a,b,c] << sql.rows("select a,b,c from maxdata")
where:
row << sql.rows("select * from maxdata")
// pick apart columns
a = row.a
b = row.b
c = row.c
43 / 65
Ignore some variable
where:
[a,b] << [[1,2,3],[1,2,3],[4,5,6]]
[a, b, _, c] << sql.rows("select * from maxdata")
44 / 65
Combine data tables, pipes and
assignments
where:
a | _
3 | _
7 | _
0 | _
b << [5, 0, 0]
c = a > b ? a : b
45 / 65
Unrolled method names
parameters
Property Access:
def "#person is #person.age years old"() {...}
Zero-argument method call:
def "#person.name.toUpperCase()"() { ... }
46 / 65
Interaction Based Testing
47 / 65
Mocking
48 / 65
Create Mock
Mocks are Lenient (return default value for undefined mock
calls)
Subscriber subscriber = Mock()
def subscriber2 = Mock(Subscriber)
49 / 65
Using Mock
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello") //subsriber should call
receive with "hello" once.
1 * subscriber2.receive("hello")
}
50 / 65
Cardinality
1 * subscriber.receive("hello") // exactly one call
0 * subscriber.receive("hello") // zero calls
(1..3) * subscriber.receive("hello") // between one and three
calls (inclusive)
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
_ * subscriber.receive("hello") // any number of calls,
including zero
51 / 65
Constraints
52 / 65
Target
A call to `subscriber`:
1 * subscriber.receive("hello")
A call to any mock object:
1 * _.receive("hello")
53 / 65
Method
A method named 'receive'
1 * subscriber.receive("hello")
A method whose name matches the given regular
expression. Here: method name starts with 'r' and
ends with 'e'.
1 * subscriber./r.*e/("hello")
54 / 65
Argument
1 * subscriber.receive("hello") // an argument that is
equal to the String "hello"
1 * subscriber.receive(!"hello") // an argument that is
unequal to the String "hello"
1 * subscriber.receive() // the empty argument list
(would never match in our example)
1 * subscriber.receive(_) // any single argument
(including null)
1 * subscriber.receive(*_) // any argument list
(including the empty argument list)
55 / 65
Argument
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 the given predicate
// (here: message length is greater than 3)
56 / 65
Specify mock calls at creation
class MySpec extends Specification {
Subscriber subscriber = Mock {
1 * receive("hello")
1 * receive("goodbye")
}
}
57 / 65
Group interactions
with(mock) {
1 * receive("hello")
1 * receive("goodbye")
}
58 / 65
Stubbing
Stubs don’t have cardinality (matches invocation
anyTimes)
def subscriber = Stub(Subscriber)
...
subscriber.receive(_) >> "ok"
Whenever the subscriber receives a message, make
it respond with ‘ok’.
59 / 65
Returning different values on
sucessive calls
subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw
new InternalError() } >> "ok"
60 / 65
Extensions
@Ignore(reason = "TODO")
@IgnoreRest
@IgnoreIf({ spock.util.environment.Jvm.isJava5()) })
@Requires({ os.windows })
@Timeout(5)
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
@Title("This tests if..."
@Narrative("some detailed explanation")
@Issue("http://redmine/23432")
@Subject
61 / 65
Disadvantages of Spock
Due to some differences between Java and Groovy, for
example, different numeric data types, some tests on Groovy
look more cumbersome because type casting is required.
Also Spock is not good friends with the Spring Framework.
Here is an example of how you can use objects from the
Spring context:
62 / 65
Spring Boot
The recommended way to use Spock mocks in
@WebMvcTest tests, is to use an embedded config
annotated with @TestConfiguration and to create the
mocks using the DetachedMockFactory.
63 / 65
@WebMvcTest
class WebMvcTestIntegrationSpec extends Specification {
@Autowired
MockMvc mvc
@Autowired
HelloWorldService helloWorldService
def "spring context loads for web mvc slice"() {
given:
helloWorldService.getHelloMessage() >> 'hello world'
expect: "controller is available"
mvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(status().isOk())
.andExpect(content().string("hello world"))
}
@TestConfiguration
static class MockConfig {
def detachedMockFactory = new DetachedMockFactory();
@Bean
HelloWorldService helloWorldService() {
return detachedMockFactory.Stub(HelloWorldService)
}
}
}
64 / 65
Sources

http://wittyginger.com/post/groovy-is-still-better-than-java/

http://jakubdziworski.github.io/java/groovy/spock/2016/05/14/spock-chea

http://spockframework.org/spock/docs/1.1-rc-3/module_spring.html
65 / 65
Thanks ;)

More Related Content

What's hot

Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introdução
Josino Rodrigues
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
John Slick
 

What's hot (20)

Basic i/o & file handling in java
Basic i/o & file handling in javaBasic i/o & file handling in java
Basic i/o & file handling in java
 
Kotlin as a Better Java
Kotlin as a Better JavaKotlin as a Better Java
Kotlin as a Better Java
 
Core java
Core javaCore java
Core java
 
Unit/Integration Testing using Spock
Unit/Integration Testing using SpockUnit/Integration Testing using Spock
Unit/Integration Testing using Spock
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Effective Java - Enum and Annotations
Effective Java - Enum and AnnotationsEffective Java - Enum and Annotations
Effective Java - Enum and Annotations
 
C# Basics
C# BasicsC# Basics
C# Basics
 
Core java concepts
Core java  conceptsCore java  concepts
Core java concepts
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introdução
 
java.io - streams and files
java.io - streams and filesjava.io - streams and files
java.io - streams and files
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Java Generics - by Example
Java Generics - by ExampleJava Generics - by Example
Java Generics - by Example
 
C# Constructors
C# ConstructorsC# Constructors
C# Constructors
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features Overview
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
REST vs. GraphQL: Critical Look
REST vs. GraphQL: Critical LookREST vs. GraphQL: Critical Look
REST vs. GraphQL: Critical Look
 
Bowling Game Kata by Robert C. Martin
Bowling Game Kata by Robert C. MartinBowling Game Kata by Robert C. Martin
Bowling Game Kata by Robert C. Martin
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassJava Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug Class
 

Similar to Spock Framework

"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres..."The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
Edge AI and Vision Alliance
 
4CS4-25-Java-Lab-Manual.pdf
4CS4-25-Java-Lab-Manual.pdf4CS4-25-Java-Lab-Manual.pdf
4CS4-25-Java-Lab-Manual.pdf
amitbhachne
 

Similar to Spock Framework (20)

The genesis of clusterlib - An open source library to tame your favourite sup...
The genesis of clusterlib - An open source library to tame your favourite sup...The genesis of clusterlib - An open source library to tame your favourite sup...
The genesis of clusterlib - An open source library to tame your favourite sup...
 
"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres..."The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
"The OpenCV Open Source Computer Vision Library: Latest Developments," a Pres...
 
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019
 
00_Introduction to Java.ppt
00_Introduction to Java.ppt00_Introduction to Java.ppt
00_Introduction to Java.ppt
 
Need 4 Speed FI
Need 4 Speed FINeed 4 Speed FI
Need 4 Speed FI
 
Implementing Quality on a Java Project
Implementing Quality on a Java ProjectImplementing Quality on a Java Project
Implementing Quality on a Java Project
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast Lane
 
Unit testing - A&BP CC
Unit testing - A&BP CCUnit testing - A&BP CC
Unit testing - A&BP CC
 
Java scjp-part1
Java scjp-part1Java scjp-part1
Java scjp-part1
 
OpenDaylight Developer Experience 2.0
 OpenDaylight Developer Experience 2.0 OpenDaylight Developer Experience 2.0
OpenDaylight Developer Experience 2.0
 
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPInria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projects
 
What's New in Groovy 1.6?
What's New in Groovy 1.6?What's New in Groovy 1.6?
What's New in Groovy 1.6?
 
4CS4-25-Java-Lab-Manual.pdf
4CS4-25-Java-Lab-Manual.pdf4CS4-25-Java-Lab-Manual.pdf
4CS4-25-Java-Lab-Manual.pdf
 
Code quality par Simone Civetta
Code quality par Simone CivettaCode quality par Simone Civetta
Code quality par Simone Civetta
 
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem novaKotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
 
System verilog important
System verilog importantSystem verilog important
System verilog important
 
Groovy In the Cloud
Groovy In the CloudGroovy In the Cloud
Groovy In the Cloud
 
Test Driven In Groovy
Test Driven In GroovyTest Driven In Groovy
Test Driven In Groovy
 

Recently uploaded

Recently uploaded (20)

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
 
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
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
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
 
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...
 
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
 
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purityAPVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
 
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdfStrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
 
INGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by DesignINGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by Design
 
Crafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM IntegrationCrafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM Integration
 
AI Hackathon.pptx
AI                        Hackathon.pptxAI                        Hackathon.pptx
AI Hackathon.pptx
 
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
 
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
 
Workforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdfWorkforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdf
 
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
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
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
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
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
 

Spock Framework

  • 1. 1 / 65 Spock Framework Code Factory presentation, Jul, 2018 Stavila Leonid
  • 2. 2 / 65 Introduction Many modern programming languages are popular due to the libraries and frameworks that are written on them. Where would Ruby be without Rails?
  • 3. 3 / 65 The Java visiting card is primarily Spring and Hibernate
  • 4. 4 / 65 Scala glorified the Akka framework
  • 5. 5 / 65 Groovy is primarily Gradle and Spock
  • 6. 6 / 65 Kotlin... To be honest, it seems to me that the ratings of this language are artificially overstated.
  • 7. 7 / 65 So, Spock To begin with, this test framework is written in Groovy. For large projects, this language is not recommended, like and Scala, but for small scripts and tests it is very suitable.
  • 8. 8 / 65 Groovy In fact, this language is a superset of Java, that is, if you don’t know how to write-write in Java. But knowledge of Groovy syntax can save you time. Groovy is a kind of script version of Java. It's simpler, more compact, but at the same time provides all the power of the JVM.
  • 9. 9 / 65 A classic example is `hello world` Java: System.out.println("Hello world!"); Groovy: println 'Hello world!'
  • 10. 10 / 65 Economy println 'Hello world!'  The length of the method name  Two brackets  Quotes. Single quotes are easier to type  Semicolon
  • 11. 11 / 65 Reading data from a file: BufferedReader br = new BufferedReader(new FileReader("file.txt")); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); System.out.println("line = " + line); } } finally { if (br != null) { br.close(); } }
  • 12. 12 / 65 This hulk can be placed in one line new File("file.txt") .eachLine { println "line = $it" } But most of all I like Groovy's ability to laconically process collections. Even revolutionary innovations in Java 8 do not approach them.
  • 13. 13 / 65 Working with a collection  Java: List<Integer> results = Stream.of(1, 2, 3) .map(v -> v * 2) .collect(Collectors.toList());  Groovy: List results = [1, 2, 3] .collect { it * 2 }
  • 14. 14 / 65 Example of filtering  Java: List<Integer> evenNumbers = Stream.of(1, 2, 3, 4).filter(v -> v % 2 == 0).collect(Collectors.toList());  Groovy: List evenNumbers = [1, 2, 3, 4] .findAll { it % 2 == 0 }
  • 15. 15 / 65 Let's get back to testing In the world of Java, JUnit rules in conjunction with any of the available frameworks for mocking (Mockito, EasyMock, PowerMock, etc.). This is enough to write a test of any complexity, but this classic approach has drawbacks.
  • 16. 16 / 65  There is no way to give tests a normal and understandable names. The names of methods in the style of Camel Case are not considered, and Junit 5 has not yet received the proper distribution. ‘shouldAddToCartIfItemIsAvailaibleAndThe LimitIsNotExceededAnd…..’.
  • 17. 17 / 65  Tests are overloaded with verbose constructs, such as Collections.singletonList(), Verify(…), any(MyAwesomeAbstract- FactoryBaseClass.class) and so on.
  • 18. 18 / 65  Because these frameworks don’t allow a normal way of dividing the testing process into a configuration phase, testing itself and checking the result, very often the tests look just like a pile of incomprehensible, and bizarrely mixed code.
  • 19. 19 / 65  In order to test incoming arguments, you need to build cumbersome structures.
  • 20. 20 / 65  There is no normal support for parameterized tests. As a result, to cover all cases, we need to write many similar tests.
  • 21. 21 / 65 When the tests begin to bring a lot of pain, we try not to use them, or we write trashy, and as a result we then face even greater pain. Bad tests don’t guarantee that any new code change will not break anything else.
  • 22. 22 / 65 Tests written on Groovy look smoother, they are easier to read and understand. But some people did not think it was enough, and after a while a group of enthusiasts wrote their test framework, Spock.
  • 23. 23 / 65 Spock Framework For many years, programmers have come to the conclusion that the more code resembles the usual sentences of the human language, the easier and faster it can be understood.
  • 24. 24 / 65 In programming practice, this is not always applicable. But in testing, due to the fact that all tests are similar in their idea, this practice is successfully used. Programming languages that allow you to flexibly change your syntax, were able to realize this idea to the fullest extent.
  • 25. 25 / 65 Currently, tests can be started by customers who are far from programming. All that is needed is to write the business requirements in a compact form. Next, programmers will simply translate this test into code. For example: "When the user press the start button. then the menu is shown as in the picture".
  • 26. 26 / 65 A simpler example Addition of numbers 2 and 2 must return 4 This short formulation can already be used as a test name. It remains only to describe his body. As in any other test, we have the initial data, the operation that we need to test and check the result.
  • 27. 27 / 65 This can be described in three words: given, when, then: Addition of numbers 2 and 2 must return 4  given: 2, 2  when: 2 + 2  then: 4 This approach is called BDD (Behavior Driven Development).
  • 28. 28 / 65 Spock is a modern framework for testing. It's written in Groovy, includes tools for stubbing and mocking and embodies the idea of BDD. In fact, this is a domain specific language (DSL), created specifically for writing tests. It is an extension of the Junit runner and you do not have to change anything in the infrastructure to run these tests.
  • 29. 29 / 65 Advantages  Groovy is not as verbose as Java  The special syntax is aimed specifically at testing  Built-in support for Stubs and Mocks  Extends Junit runner  Simple testing with parameters  Keywords for all testing phases (given, when, then …)  Ease of describing methods  Many other specific features
  • 31. 31 / 65 Specification Template class MyFirstSpecification extends Specification { // fields // fixture methods // feature methods // helper methods }
  • 32. 32 / 65 Fixture Methods Run before every feature method: def setup() {} Run after every feature method: def cleanup() {} Run before the first feature method: def setupSpec() {} Run after the last feature method:
  • 33. 33 / 65 Blocks Order  given: data initialization goes here (includes creating mocks)  when: invoke your test subject here and assign it to a variable  then: assert data here  cleanup: optional  where: optional: provide parameterized data (tables or pipes)
  • 34. 34 / 65 Or  given  expect: combines when with then  cleanup  where
  • 35. 35 / 65 Junit comparison Spock JUnit Specification Test class setup() @Before cleanup() @After setupSpec() @BeforeClass cleanupSpec() @AfterClass Feature Test Feature method Test method Data-driven feature Theory Condition Assertion Exception condition @Test(expected=…)​ Interaction Mock expectation (e.g. in Mockito)
  • 36. 36 / 65 Data Driven Testing
  • 37. 37 / 65 Data Tables class Math 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 // passes 7 | 4 || 4 // fails 0 | 0 || 0 // passes
  • 38. 38 / 65 Unrolling A method annotated with @Unroll will have its rows from data table reported independently: @Unroll def "maximum of two numbers"() { ... }
  • 39. 39 / 65 Result with Unroll maximum of two numbers[0] PASSED maximum of two numbers[1] FAILED Math.max(a, b) == c | | | | | | 7 0 | 7 42 false
  • 40. 40 / 65 Result Without Unroll We have to figure out which row failed manually maximum of two numbers FAILED Condition not satisfied: Math.max(a, b) == c | | | | | | 7 0 | 7 42 false
  • 41. 41 / 65 Data Pipes Right side must be Collection, String or Iterable. where: a << [3, 7, 0] b << [5, 0, 0] c << [5, 7, 0]
  • 42. 42 / 65 Multi-Variable Data Pipes where: [a,b,c] << sql.rows("select a,b,c from maxdata") where: row << sql.rows("select * from maxdata") // pick apart columns a = row.a b = row.b c = row.c
  • 43. 43 / 65 Ignore some variable where: [a,b] << [[1,2,3],[1,2,3],[4,5,6]] [a, b, _, c] << sql.rows("select * from maxdata")
  • 44. 44 / 65 Combine data tables, pipes and assignments where: a | _ 3 | _ 7 | _ 0 | _ b << [5, 0, 0] c = a > b ? a : b
  • 45. 45 / 65 Unrolled method names parameters Property Access: def "#person is #person.age years old"() {...} Zero-argument method call: def "#person.name.toUpperCase()"() { ... }
  • 46. 46 / 65 Interaction Based Testing
  • 48. 48 / 65 Create Mock Mocks are Lenient (return default value for undefined mock calls) Subscriber subscriber = Mock() def subscriber2 = Mock(Subscriber)
  • 49. 49 / 65 Using Mock def "should send messages to all subscribers"() { when: publisher.send("hello") then: 1 * subscriber.receive("hello") //subsriber should call receive with "hello" once. 1 * subscriber2.receive("hello") }
  • 50. 50 / 65 Cardinality 1 * subscriber.receive("hello") // exactly one call 0 * subscriber.receive("hello") // zero calls (1..3) * subscriber.receive("hello") // between one and three calls (inclusive) (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls _ * subscriber.receive("hello") // any number of calls, including zero
  • 52. 52 / 65 Target A call to `subscriber`: 1 * subscriber.receive("hello") A call to any mock object: 1 * _.receive("hello")
  • 53. 53 / 65 Method A method named 'receive' 1 * subscriber.receive("hello") A method whose name matches the given regular expression. Here: method name starts with 'r' and ends with 'e'. 1 * subscriber./r.*e/("hello")
  • 54. 54 / 65 Argument 1 * subscriber.receive("hello") // an argument that is equal to the String "hello" 1 * subscriber.receive(!"hello") // an argument that is unequal to the String "hello" 1 * subscriber.receive() // the empty argument list (would never match in our example) 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (including the empty argument list)
  • 55. 55 / 65 Argument 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 the given predicate // (here: message length is greater than 3)
  • 56. 56 / 65 Specify mock calls at creation class MySpec extends Specification { Subscriber subscriber = Mock { 1 * receive("hello") 1 * receive("goodbye") } }
  • 57. 57 / 65 Group interactions with(mock) { 1 * receive("hello") 1 * receive("goodbye") }
  • 58. 58 / 65 Stubbing Stubs don’t have cardinality (matches invocation anyTimes) def subscriber = Stub(Subscriber) ... subscriber.receive(_) >> "ok" Whenever the subscriber receives a message, make it respond with ‘ok’.
  • 59. 59 / 65 Returning different values on sucessive calls subscriber.receive(_) >>> ["ok", "error", "error", "ok"] subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw new InternalError() } >> "ok"
  • 60. 60 / 65 Extensions @Ignore(reason = "TODO") @IgnoreRest @IgnoreIf({ spock.util.environment.Jvm.isJava5()) }) @Requires({ os.windows }) @Timeout(5) @Timeout(value = 100, unit = TimeUnit.MILLISECONDS) @Title("This tests if..." @Narrative("some detailed explanation") @Issue("http://redmine/23432") @Subject
  • 61. 61 / 65 Disadvantages of Spock Due to some differences between Java and Groovy, for example, different numeric data types, some tests on Groovy look more cumbersome because type casting is required. Also Spock is not good friends with the Spring Framework. Here is an example of how you can use objects from the Spring context:
  • 62. 62 / 65 Spring Boot The recommended way to use Spock mocks in @WebMvcTest tests, is to use an embedded config annotated with @TestConfiguration and to create the mocks using the DetachedMockFactory.
  • 63. 63 / 65 @WebMvcTest class WebMvcTestIntegrationSpec extends Specification { @Autowired MockMvc mvc @Autowired HelloWorldService helloWorldService def "spring context loads for web mvc slice"() { given: helloWorldService.getHelloMessage() >> 'hello world' expect: "controller is available" mvc.perform(MockMvcRequestBuilders.get("/")) .andExpect(status().isOk()) .andExpect(content().string("hello world")) } @TestConfiguration static class MockConfig { def detachedMockFactory = new DetachedMockFactory(); @Bean HelloWorldService helloWorldService() { return detachedMockFactory.Stub(HelloWorldService) } } }