If we write a specification for a specific class we can indicate that class with the @Subject
annotation. This annotation is only for informational purposes, but can help in making sure we understand which class we are writing the specifications for. The annotation can either be used at class level or field level. If we use the annotation at class level we must specify the class or classes under test as argument for the annotation. If we apply the annotation to a field, the type of the field is used as the class under test. The field can be part of the class definition, but we can also apply the @Subject
annotation to fields inside a feature method.
In the following example Spock specification we write a specification for the class Greet
. The definition of the Greet
class is also in the code listing. We use the @Subject
annotation on the field greet
to indicate this instance of the Greet
class is the class we are testing here. The code also works with the @Subject
annotation, but it adds more clarity to the specification.
Continue reading →
The MarkupTemplateEngine
added in Groovy 2.3 is very powerful. We can define layout templates with common markup we want to be used in multiple other templates. In the layout template we define placeholders for variables and content blocks surrounded by shared markup. We define values for these variables and content blocks in the actual template. We even can choose to propagate model attributes from the template to the layout template. Let's first create a layout template with the name main.tpl
:
// File: main.tpl
html {
head {
// Use pageTitle layout property.
title(pageTitle)
}
body {
section(id: 'main') {
// Render mainContents layout property.
mainContents()
}
section(id: 'actions') {
// Render actions layout property.
actions()
}
footer {
// A template is also Groovy code, we can
// define new variables or methods.
// pubDate should be set via original template
// model.
def generatedOn = pubDate ?: new Date()
p("Generated on ${dateFormat(generatedOn)}")
}
}
}
def dateFormat(date) {
date.format('dd-MM-yyyy')
}
Continue reading →
Since Groovy 2.3 we can use the MarkupTemplateEngine
to generate XML/HTML. We can write our templates using a builder syntax. Inside our templates we can define nested templates. These nested templates contain builder syntax code and can use objects that are passed as attributes to the nested template. To invoke a nested template we must use the fragment
method and pass a Map
with attributes that is used in the nested template. We can re-use nested templates inside our template.
In the following sample code we define two nested templates: faIcon
and list
. Inside our template we use the fragment
method to call these nested templates and we set values to the attributes that are used in the nested templates:
Continue reading →
Since Groovy 2.3 we can use the new MarkupTemplateEngine
to generate XML/HTML content. The engine compiles the template for better performance and optionally provides type checking on model attributes used in the template. We can configure the template engine to use a custom base template class instead of the default BaseTemplate
. In our custom template class we can add new methods that can be invoked from our template content.
Let's create a new base template class with an icon
method to output valid FontAwesome markup:
Continue reading →
Since Groovy 2.3 the JSON parser has improved and is really a performant parser for JSON payload. JSON must be formatted in a strict way, for example all keys must be enclosed in double quotes. But what if we have JSON which not applies to the strict specification? For example a configuration file written in JSON and we want to add comments to this file. Or use single quotes for keys, or just leave all the quotes out. We can now specify the type JsonParseType.LAX
for our JSON parser and we can now parse JSON which doesn't apply to the strict specification.
import groovy.json.*
import static groovy.json.JsonParserType.LAX as RELAX
def jsonText = '''
{
message: {
/* Set header of message */
header: {
"from": 'mrhaki',
'to': ["Groovy Users", "Java Users"]
}
# Include a little body for the message.
'body': "Check out Groovy's gr8 JSON support."
}
}
'''
def json = new JsonSlurper().setType(RELAX).parseText(jsonText)
def header = json.message.header
assert header.from == 'mrhaki'
assert header.to[0] == 'Groovy Users'
assert header.to[1] == 'Java Users'
assert json.message.body == "Check out Groovy's gr8 JSON support."
Continue reading →
We can use data pipes to write data driven tests in Spock. A data pipe (<<
) is fed by a data provider. We can use Collection
objects as data provider, but also String
objects and any class that implements the Iterable
interface. We can write our own data provider class if we implement the Iterable
interface.
In the following sample code we want to test the female
property of the User
class. We have the class MultilineProvider
that implements the Iterable
interface. The provider class accepts a multiline String
value and returns the tokenized result of each line in each iteration.
Continue reading →
We can write data driven tests with Spock. We can specify for example a data table or data pipes in a where:
block. If we use a data pipe we can specify a data provider that will return the values that are used on each iteration. If our data provider returns multiple results for each row we can assign them immediately to multiple variables. We must use the syntax [var1, var2, var3] << providerImpl
to assign values to the data variables var1
, var2
and var3
. We know from Groovy the multiple assignment syntax with parenthesis ((var1, var2, var3)
), but with Spock we use square brackets.
In the following sample specification we have a simple feature method. The where:
block shows how we can assign the values from the provider to multiple data variables. Notice we can skip values from the provider by using a _
to ignore the value.
Continue reading →
We can use the @Ignore
and @IgnoreRest
annotation in our Spock specifications to not run the annotated specifications or features. With the @IgnoreIf
annotation we can specify a condition that needs to evaluate to true
to not run the feature or specification. The argument of the annotation is a closure. Inside the closure we can access three extra variables: properties
(Java system properties), env
(environment variables) and javaVersion
.
In the following Spock specification we have a couple of features. Each feature has the @IgnoreIf
annotation with different checks. We can use the extra variables, but we can also invoke our own methods in the closure argument for the annotation:
Continue reading →
In a previous blog post we have seen how we can use a BaseScript
AST transformation to set a base script class for running scripts. Since Groovy 2.3 we can apply the @BaseScript
annotation on package
and import
statements. Also we can implement a run
method in our Script
class in which we call an abstract method. The abstract method will actually run the script, so we can execute code before and after the script code runs by implementing logic in the run
method.
In the following sample we create a Script
class CustomScript
. We implement the run
method and add the abstract method runCode
:
Continue reading →
Since Groovy 2.3 we can use the @Sortable
annotation to make a class implement the Comparable
interface. Also new comparator
methods are added. All properties of a class are used to implement the compareTo
method. The order of the properties determines the priority used when sorting. With the annotation parameters includes
and excludes
we can define which properties of the class need to be used to implement the compareTo
method.
In the following class with the name Course
we define three properties title
, beginDate
and maxAttendees
. We also apply the @Sortable
annotation. Notice we cannot use int
as a type, because it doesn't implement the Comparable
interface. The class Integer
does.
Continue reading →
We have seen some features of the @Builder
AST transformation in previous and other blog post. We can use another strategy to let the AST transformation generate a class where the class only has a constructor that accepts a builder class. And with @CompileStatic
we can even make sure that all required properties must have a value set by the builder before the constructor accepts the argument. We use the builderStrategy
annotation parameter and set it to InitializerStrategy
:
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy
@Builder(builderStrategy = InitializerStrategy)
class Message {
String from, to, subject, body
}
def message = Message.createInitializer()
.from('mrhaki@mrhaki.com')
.subject('Groovy 2.3 is released')
// Returned object is not Message, but
// internal class Message$MessageInitializer
assert !(message instanceof Message)
// Now we can use the initializer in the
// only constructor of Message.
def messageInstance = new Message(message)
assert messageInstance instanceof Message
assert messageInstance.from == 'mrhaki@mrhaki.com'
assert messageInstance.subject == 'Groovy 2.3 is released'
Continue reading →
In a previous post we learned about the new @Builder
AST transformation introduced in Groovy 2.3. We applied to the annotation to our class files and we got a nice fluent API to set property values. But what if we cannot change the class itself, for example if we want to create a fluent API for classes in an external library. Then we can still use the @Builder
AST transformation but we use a different strategy. We can define the builder strategy via a annotation parameter.
In the following sample we assume the Message
class is from an external library and we cannot or do not want to change the class definition. We create a new Groovy class and set the @Builder
annotation on this new class. We use the annotation parameters builderStrategy
to indicate the generated code is not for the new class, but for the class set with the annotation parameter forClass
.
Continue reading →