Loading...

Tuesday, June 29, 2010

Spocklight: Introduction to Spock Testing

In this blog entry we will start with a simple Spock specification for a Groovy class we create. We can learn why to use Spock on the Spock website. In this article we show with code how our tests will work with Spock. To get started with this sample we need Gradle installed on our machine and nothing else. The current release of Gradle at the time of writing this entry is 0.9-preview-3.

First we need to create a new directory for our little project and then we create a new build.gradle file:

$ mkdir spock-intro
$ cd spock-intro
$ mkdir -p src/main/groovy/com/mrhaki/blog src/test/groovy/com/mrhaki/blog
// File: build.gradle
apply plugin: 'groovy'

repositories {
    mavenCentral()
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.7.3'
    testCompile 'org.spockframework:spock-core:0.4-groovy-1.7'
}

Next we create our tests, but in Spock they are called specifications. We only need to extend the spock.lang.Specification and we get all the Spock magic in our hands. We start simple by defining a specification where we want to count the number of users in a UserService class. We are going to create the UserService class later, we start first with our specification:

package com.mrhaki.blog

import spock.lang.Specification

class UserServiceSpecification extends Specification {

    def "Return total number of users"() {
        setup: 'Create UserService instance with 2 users'
        UserService userService = new UserService(users: ['mrhaki', 'hubert'])

        expect: 'Invoke count() method'
        2 == userService.count()
    }

}

Notice at line 6 how we can use very descriptive method names by using String literals. Next we create an instance of the UserService class and pass a list of two users at line 8. And then we check if the return value is the expected value 2 with a simple assertion statement. Spock provides a very readable way to write code. Mostly we first setup code for testing, run the code and finally test the results. This logic is supported nicely by Spock by using the labels setup and expect. Later on we see more of these labels.

Before we run the test we create our UserService class:

package com.mrhaki.blog

class UserService {

    Collection<String> users

    int count() {
        users ? users.size() : 0
    }

}

We can run our code and test with the following command:

$ gradle test
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:compileTestJava
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test

BUILD SUCCESSFUL

Total time: 12.475 secs

The source files are compiled and our specification is run. We get the BUILD SUCCESSFUL message indicating our test runs fine. If the test would fail we can open build/reports/tests/index.html or build/test-results/TEST-com.mrhaki.blog.UserServiceSpecification.xml to see the failure.

We specified the count() method must return the number of users, but we only check it for 2 elements, but what if we want to test to see if 0 and 1 user also return the correct count value? We can create new methods in our specification class, but Spock makes it so easy to do this elegantly:

package com.mrhaki.blog

import spock.lang.Specification

class UserServiceSpecification extends Specification {

    def "Return total number of users"() {
        setup: 'Create UserService instance with users'
        UserService userService = new UserService(users: userList)

        expect: 'Invoke count() method'
        expectedCount == userService.count()

        where:
        expectedCount   | userList
        0               | null
        0               | []
        1               | ['mrhaki']
        2               | ['mrhaki', 'hubert']
    }

}

So what happens here? We use a new label where which contains a data table. Each row of the data table represent a new test run with the data from the row. In the setup block we used an unbound variable userList and in the expect block the unbound variable expectedCount. The variables get their values from the data table rows in the where block. So the first run the UserService instances gets null assigned to the users property and we expect the value 0 to be returned by the count() method. In the second run we pass an empty list and expect also 0 from the count() method. We have four rows, so our test is run four times when we invoke $ gradle test.

We can make the fact that four tests are run explicit by using the @Unroll annotation. We can use a String as argument describing the specific variable values used in a run. If we use the # followed by the unbound variable name will it be replaced when we run the code:

package com.mrhaki.blog

import spock.lang.Specification
import spock.lang.Unroll

class UserServiceSpecification extends Specification {

    @Unroll("Expect to count #expectedCount users for following list #userList")
    def "Return total number of users"() {
        setup: 'Create UserService instance with users'
        UserService userService = new UserService(users: userList)

        expect: 'Invoke count() method'
        expectedCount == userService.count()

        where:
        expectedCount   | userList
        0               | null
        0               | []
        1               | ['mrhaki']
        2               | ['mrhaki', 'hubert']
    }

}

The generated XML with the test result contains the four runs with their specific names:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" failures="0" hostname="ci-test" name="com.mrhaki.blog.UserServiceSpecification" tests="4" time="0.707" timestamp="2010-06-29T18:17:24">
  <properties />
  <testcase classname="com.mrhaki.blog.UserServiceSpecification" name="Expect to count 0 users for following list null" time="0.152" />
  <testcase classname="com.mrhaki.blog.UserServiceSpecification" name="Expect to count 0 users for following list []" time="0.027" />
  <testcase classname="com.mrhaki.blog.UserServiceSpecification" name="Expect to count 1 users for following list [mrhaki]" time="0.0050" />
  <testcase classname="com.mrhaki.blog.UserServiceSpecification" name="Expect to count 2 users for following list [mrhaki, hubert]" time="0.0010" />
  <system-out><![CDATA[]]></system-out>
  <system-err><![CDATA[]]></system-err>
</testsuite>

This concludes the introduction to Spock testing. In the future we learn more about Spock and the great features it provide to make writing tests easy and fun.

Monitoring Remote Java Applications with jstatd

To monitor a remote Java application with VisualVM is easy when we use jstatd. We need to start jstatd on the remote machine, make a connection from VisualVM to the remote machine and we can monitor all running Java applications.

Sample security policy file:

grant codebase "file:${java.home}/../lib/tools.jar" {

   permission java.security.AllPermission;

};

We can run jstatd with:

$ jstatd -J-Djava.security.policy=jstatd.all.policy

Sunday, June 27, 2010

Groovy Goodness: Synchronized Annotation for Synchronizing Methods

Since Groovy 1.7.3 we have a new AST transformation: @Synchronized. This annotation is based on the Project Lombok Synchronized annotation. We can use the annotation on instance and static methods. The annotation will create a lock variable in our class (or we can use an existing variable) and the code is synchronized on that lock variable. Normally with the synchronized keyword the lock is on this, but that can have side-effects.

import groovy.transform.Synchronized

class Util {
    private counter = 0
    
    private def list = ['Groovy']
    
    private Object listLock = new Object[0]
    
    @Synchronized
    void workOnCounter() {
        assert 0 == counter
        counter++
        assert 1 == counter
        counter --
        assert 0 == counter
    }
    
    @Synchronized('listLock')
    void workOnList() {
        assert 'Groovy' == list[0]
        list << 'Grails'
        assert 2 == list.size()
        list = list - 'Grails'
        assert 'Groovy' == list[0]
    }
}

def util = new Util()
def tc1 = Thread.start { 
    100.times { 
        util.workOnCounter()
        sleep 20 
        util.workOnList()
        sleep 10
    } 
}
def tc2 = Thread.start { 
    100.times { 
        util.workOnCounter()
        sleep 10 
        util.workOnList()
        sleep 15
    } 
}
tc1.join()
tc2.join()

Sample Chapter Groovy for Domain-Specific Languages Book

If we want to learn more about "Building a Builder" we can download a sample chapter on this subject from the book "Groovy for Domain-Specific Languages".

Download Building a Builder

Sunday, June 20, 2010

Groovy Goodness: Strip Leading Spaces from Lines with Margin

Since Groovy 1.7.3 we can use the stripMargin() method to strip characters up to and including a margin character from multiline strings. The default character is the pipe symbol (|), but we can pass a parameter to the method and use a custom character.

def s = '''\
        |Groovy
        |Grails
        |Griffon'''
        
assert '''\
Groovy
Grails
Griffon''' == s.stripMargin()

def s1 = '''\
   * Gradle
   * GPars
   * Spock''' 
   
assert '''\
 Gradle
 GPars
 Spock''' == s1.stripMargin("* ")

Friday, June 18, 2010

Grails Goodness: Refactoring Criteria Contents

Grails adds a Hibernate criteria builder DSL so we can create criteria's using a builder syntax. When we have criteria with a lot of restrictions or conditional code inside the builder we can refactor this easily. We look at a simple criteria to show this principle, but it can be applied to more complex criteria's.

// Original criteria builder.
def list = Domain.withCriteria {
    ilike 'title', 'Groovy%'
    le 'postedDate', new Date()
}

// Refactor
def list2 = Domain.withCriteria {
    title delegate, 'Groovy%'
    alreadyPosted delegate
}

private void title(builder, String query) {
    builder.ilike 'title', query
}

private void alreadyPosted(builder) {
    builder.le 'postedDate', new Date()
}

Tuesday, June 15, 2010

Groovy Goodness: Text Translation

In Groovy 1.7.3 the tr() method is added to the String class. With this method we can do translations in String values. We define a source set of characters that need to be replaced by a replacement set of characters. We can also use a regular expression style (remember it is not a real regular expression) to define a range of characters.

If the replacement set is smaller than the source set, than the last character of the replacement set is used for the remaining source set characters.

// Source set and replacement set are equal size.
assert 'I 10v3 9r00vy' == 'I love Groovy'.tr('loeG', '1039')

// Regular expression style range
assert 'mrHAKI' == 'mrhaki'.tr('a-k', 'A-K')

// Replacement set is smaller than source set.
assert 'Gr8888' == 'Groovy'.tr('ovy', '8')

Groovy Goodness: Represent a List as String

In Groovy we can use the toListString() method to get a String representation for a given collection. And since Groovy 1.7.3 we can use a parameter to determine a maximum size of the resulting String. This value is used to stop the String representation after approximately the given size and append three dots (...) to the result.

def list = ['Groovy', 'Clojure', 'Java']

def listString = list.toListString()
def abbreviated = list.toListString(12)

assert '[Groovy, Clojure, Java]' == listString
assert '[Groovy, Clojure, ...]' == abbreviated

Monday, June 14, 2010

Groovy Goodness: Getting Head And Tail From an Array of Objects

We could already use the head() and tail() methods on Collection objects in Groovy, but in Groovy 1.7.3 we can use them on Object arrays as well.

String[] stringArray = ['Groovy', 'Grails', 'Spock']

assert 'Groovy' == stringArray.head()
assert ['Grails', 'Spock'] == stringArray.tail()
assert 'Groovy' == stringArray.first()
assert 'Spock' == stringArray.last()

Groovy Goodness: Inherit Constructors From Parent Classes

We have a new transformation annotation in Groovy 1.7.3 to safe us a lot of typing when we define new classes that extend from parent classes with multiple constructors: @InheritConstructors. When we apply this transformation to our class we automatically get all constructors from the super class. This is very useful if we for example extend from java.lang.Exception, because otherwise we would have to define four constructors ourselves. The transformation adds these constructors for us in our class file. This works also for our own created classes.

import groovy.transform.InheritConstructors

@InheritConstructors
class MyException extends Exception {
}

def e = new MyException()
def e1 = new MyException('message')   // Other constructors are available.
assert 'message' == e1.message


class Person {
    String name
    
    Person(String name) {
        this.name = name
    }
}

@InheritConstructors
class Child extends Person {}

def child = new Child('Liam')
assert 'Liam' == child.name

Groovy Goodness: Create New Date from Old Date with Updates

Groovy 1.7.3 adds the updated() method to the Date and Calendar classes. We pass a Map as parameter to this method to define which fields are updated. The fields that are not mentioned are unchanged. The result is a new Date or Calendar object, our original object stays the same.

import static java.util.Calendar.*

def cal = Calendar.instance
cal[MONTH] = DECEMBER
def calNextMonth = cal.updated(month: cal[MONTH] + 1, year: 2012)

assert JANUARY == calNextMonth[MONTH]
assert 2013 == calNextMonth[YEAR]

def date = new Date()
date.set(year: 2011, month: MAY, date: 5)
def dateTenYearsAgo = date.updated(year: date[YEAR] - 10)

assert '2011-5-5' == date.format('yyyy-M-d')
assert '2001-5-5' == dateTenYearsAgo.format('yyyy-M-d')

Groovy Goodness: Use the set Method to Define a Date or Calendar Value

In a previous post we learned about the new subscript operator support in Groovy 1.7.3 for setting Date or Calendar values. But we have other new ways in Groovy 1.7.3: we can use a set() method to set the values. The method accepts a Map with the following keys: year, month, date, hourOfDay, minute and second. The keys are used to set the according values of the Date or Calendar object.

import static java.util.Calendar.*

def cal = Calendar.instance
cal.set(year: 2010, month: JULY, date: 9)

assert 'Birthday @ 2010-7-9' == 'Birthday @ ' + cal.format('yyyy-M-d')
assert FRIDAY == cal[DAY_OF_WEEK]

def date = new Date()
date.set(hourOfDay: 12, minute: 0, second: 0, year: 2010, month: JUNE, date: 1)

assert '12:00:00' == date.format('HH:mm:ss')
assert 2010 == date[YEAR]
assert JUNE == date[MONTH]
assert 1 == date.getAt(DATE)

Groovy Goodness: Setting Date and Calendar Values with Subscript Operators

In Groovy 1.7.3 we have some new ways to set the value of Date or Calendar objects. We can for example use the subscript operators (getAt() and putAt() methods) to define value for fields or get the value from a field. The fields are the Calendar constants like Calendar.YEAR, Calendar.DATE.

import static java.util.Calendar.*

def date = new Date()
// Set value with subscript operator
date[YEAR] = 2010
date[MONTH] = JUNE
date[DATE] = 14

assert 110 == date.year
assert 5 == date.month
assert 14 == date.date

// Get value with subscript operator
assert 2010 == date[YEAR]  
assert JUNE == date[MONTH]
assert 14 == date[DATE]


def cal = Calendar.instance
// Set value with subscript operator
cal[YEAR] = 2000
cal[MONTH] = DECEMBER
cal[DATE] = 25

assert '2000-12-25' == cal.format('yyyy-MM-dd')
assert 2000 == cal[YEAR]  // Get value with subscript operator

Groovy Goodness: Strip Leading Spaces from Lines

Multiline strings are very useful in Groovy. But sometimes they can mess up our code formatting especially if we want to use the multiline string's value literally. If our lines cannot start with spaces we must define our multiline string that way:

class Simple {

    String multi() {
        '''\
Multiline string
with simple 2 space
indentation.'''
    }

    // Now in Groovy 1.7.3:
    String multi173() {
        '''\
        Multiline string
        with simple 2 space
        indentation.'''.stripIndent()
    }

}

Since Groovy 1.7.3 we can strip leading spaces from such lines, so we can align the definition of our multiline string the way we want with the stripIndent() method. Groovy finds the line with the least spaces to determine how many spaces must be removed from the beginning of the line. Or we can tell the stripIndent() method how many characters must be removed from the beginning of the line.

def multi = '''\
  Multiline string
  with simple 2 space
  indentation.'''

assert '''\
Multiline string
with simple 2 space
indentation.''' == multi.stripIndent()

assert '''\
ine string
imple 2 space
ation.''' == multi.stripIndent(8)  // We can define the number of characters ourselves as well.

Groovy Goodness: Expand or Unexpand Space or Tab Delimited Text

Groovy 1.7.3 adds new functionality to the String class. For example we can use the expand() method to expand tabs in a String to spaces with a default tab stop size of 8. We can use a parameter to use a different tab stop size. But we can also go the other way around.

So if we have a tabular text based on spaces we can convert the String to a tab separated String. Here the default tab stop size is also 8, but we can use the parameter to define a different tab stop size.

// Simple ruler to display 0 up to 30
def ruler = (0..30).inject('\n') { result, c -> 
    result += (c % 10) 
}

def stringWithTabs = 'Groovy\tGrails\tGriffon'

println ruler
println stringWithTabs.expand()  // default tab stop is 8
println stringWithTabs.expand(10)  // tab stop is 10

// Output:
// 0123456789012345678901234567890
// Groovy  Grails  Griffon
/ /Groovy    Grails    Griffon

assert 'Groovy  Grails  Griffon' == stringWithTabs.expand()
assert 'Groovy    Grails    Griffon' == stringWithTabs.expand(10)


def stringWithSpaces = 'Hubert  Klein   Ikkink'
def stringWithSpaces10 = 'Hubert    Klein     Ikkink'
println ruler
println stringWithSpaces
println stringWithSpaces10

// Output:
// 0123456789012345678901234567890
// Hubert  Klein   Ikkink
// Hubert    Klein     Ikkink

assert 'Hubert\tKlein\tIkkink' == stringWithSpaces.unexpand()
assert 'Hubert\tKlein\tIkkink' == stringWithSpaces10.unexpand(10)

Groovy Goodness: Capitalize Strings

Groovy 1.7.3 adds the capitalize() method to the String class. This will capitalize the first letter of the String:

assert 'MrHaki' == 'mrHaki'.capitalize()
assert 'Groovy' == 'groovy'.capitalize()
assert 'Groovy is Gr8!' == 'groovy is Gr8!'.capitalize()

Thursday, June 10, 2010

Groovy Goodness: Get Hints About Missing Methods or Properties

Groovy helps us if for example we make a small mistake in our code. We don't only get an error message, but also a hint about a possible solution. This works also for classes we create ourselves.

In the following example we use toUppercase() instead of toUpperCase(). Notice the suggestion we get from Groovy:

$ groovy -e "println 'mrhaki'.toUppercase()"
Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.String.toUppercase() is applicable for argument types: () values: []
Possible solutions: toUpperCase(), toUpperCase(java.util.Locale), toLowerCase(), toLowerCase(java.util.Locale)
 at script_from_command_line.run(script_from_command_line:1)

Suppose we define the following script:

class User {
    String name
    String giveName() { name }
}

def u = new User(name: 'mrhaki')
println u.givenName()

When we run this script we get the following output:

$ groovy UserScript.groovy 
Caught: groovy.lang.MissingMethodException: No signature of method: User.givenName() is applicable for argument types: () values: []
Possible solutions: giveName(), getName(), setName(java.lang.String)
 at UserScript.run(UserScript.groovy:7)

Thursday, June 3, 2010

Groovy Goodness: Create Class Instance Dynamically

The Class method in Groovy has a newInstance() to dynamically create a new instance of a given class. We can use an Object array or Map as argument if we want to invoke the non-default constructor of the class.

class Blog {
    String name
    String subject
    
    Blog() {}
    
    Blog(String name, String subject) {
        this.name = name
        this.subject = subject
    }
}

def blog = Blog.newInstance()
assert !blog.name, 'Name has no value'
assert !blog.subject, 'Subject has no value'

def blog2 = Blog.newInstance(['mrhaki', 'Groovy'] as Object[])
assert 'mrhaki' == blog2.name
assert 'Groovy' == blog2.subject

def blog3 = Blog.newInstance([name:'mrhaki', subject: 'Groovy'])
assert 'mrhaki' == blog3.name
assert 'Groovy' == blog3.subject