Java Programming Tutorials

Java programming tutorials with many code examples!

Spock Framework error reporting @Unroll

Problem:

Spock Framework is powerful data-driven testing library. Its where block makes tests very concise, but sometimes when test fail how to quickly find out which dataset didn’t work?

Solution:

Error reporting in Spock Framework is very readable and works really well for simple cases like this one:

class SpockErrorReportingTest extends Specification {
    def 'should select max of two numbers'() {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        5 | 1 | 5
        9 | 9 | 8
    }
}

If you run the test you can see very readable error report:

Spock Framework error report

Spock Framework error report for failing test

The problem is that in usual Java project you run thousands of tests on build server and going to build logs to see what has failed is just too slow. Another thing is that you may have some complex setup in test that is not in assert statement, so it wouldn’t be printed in Spock’s error report.

To solve this you can use Spock Framework’s @Unroll annotation, which will show each test iteration from where block as separate test. Moreover it can print different things in test name, giving you immediate feedback. Enough talking, here’s the code:

package com.farenda.solved

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

// @Unroll can be on class level here too!
// It then acts on each test that doesn't have @Unroll already.
class SpockErrorReportingTest extends Specification {

    def 'should select max of two numbers'() {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        5 | 1 | 5
        9 | 9 | 9
    }

    // @Unroll with format inside test name:
    @Unroll
    def 'in feature: max of #a and #b should be #c'() {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        5 | 1 | 5
        9 | 9 | 9
    }

    // @Unroll with format as annotation's parameter:
    @Unroll('in unroll: max of #a and #b should be #c')
    def 'a b c'() {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        5 | 1 | 5
        9 | 9 | 8  // failing on purpose
    }
}

Running the above code gives nice list of tests with immediate visual feedback:

Spock Framework @Unroll example

Spock Framework @Unroll example

In @Unroll you can refer to any variables defined inside where block, like here:

@Unroll('the sum is: #theSum')
def 'theSum test'() {
    expect:
    Math.max(a, b) == c

    where:
    a | b | c
    5 | 1 | 5
    9 | 9 | 8

    theSum = a + b + c
}

Unit testing is so much fun with Spock Framework. Enjoy it. :-)

Share with the World!