Writing Unit Tests With Spock Framework: Creating a Maven Project

The Spock Framework is a testing and specification framework for Java and Groovy applications. Its website make a somewhat bold claim:

What makes it stand out from the crowd is its beautiful and highly expressive specification language.

Before we can verify if this claim is true, we have to create an example project that we can use for this purpose. One way to do this is to use Maven.

This blog post describes how we can create a Maven project that fulfils the following requirements:

  • It must support "normal" unit tests that use JUnit and unit tests that use the Spock Framework.
  • It must compile and run the "normal" unit tests that are found from the src/test/java directory.
  • It must compile and run the Groovy unit tests that are found from the src/test/groovy directory.
  • It must create an HTML test report that describes the test results of our unit tests that use the Spock Framework.

Let's start by getting the required dependencies.

Getting the Required Dependencies

We can get the required dependencies by declaring the following dependencies in our pom.xml file:

  • JUnit (version 4.12) is a framework that allows us to write both unit and integration tests.
  • Spock Core (version 1.0-groovy-2.4). Spock is a testing and specification framework for Java and Groovy applications.
  • Groovy All (version 2.4.4). Groovy is a dynamic programming language for the JVM.

After we have added these dependencies into our pom.xml file, its dependencies section looks as follows:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-core</artifactId>
        <version>1.0-groovy-2.4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.4</version>
        <scope>test</scope>
    </dependency>
</dependencies>
We don't have to add the JUnit and Groovy dependencies into our pom.xml file. However, if we leave them out, we have to use the JUnit and Groovy versions specified by Spock Core.

After we have added the required dependencies into our pom.xml file, we have to configure Maven to compile our unit tests.

Compiling Our Unit Tests

Because our unit tests use both Java and Groovy programming languages, we need to compile our test sources by using the GMavenPlus and Maven Compiler plugins. We can configure these plugins by following these steps:

  1. Add the GMavenPlus Plugin (version 1.5) into the pom.xml file and configure it by following these steps:
    1. Ensure that the addTestSources goal of the GMavenPlus Plugin is invoked in the initialize phase of the Maven default lifecycle. This goal adds our Groovy test sources, which are found from the src/test/groovy directory, to the project's test sources.
    2. Ensure that the testCompile goal of the GMavenPlus Plugin is invoked in the test-compile phase of the Maven default lifecycle. This goal compiles our Groovy test sources.
  2. Add the Maven Compiler Plugin (version 3.3) into the pom.xml file and configure it by following these steps:
    1. Ensure that the Java compiler accepts code that uses Java 1.8.
    2. Ensure that the compiled classes are compatible with Java 1.8.

After we have configured these plugins, the plugins section of our pom.xml looks as follows:

<plugins>
    <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.5</version>
        <executions>
            <execution>
                <goals>
					<goal>addTestSources</goal>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

We can compile our unit tests by running the following command at the command prompt:

mvn clean test-compile

When do this, we see that

  • The addTestSources and testCompile goals of the GMavenPlus Plugin are invoked.
  • the testCompile goal of the Maven Compiler Plugin is invoked.

The output of this command looks as follows:

> mvn clean test-compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Writing Unit Tests With Spock - Configuration 0.1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ unit-testing-configuration ---
[INFO] Deleting /Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/target
[INFO]
[INFO] --- gmavenplus-plugin:1.5:addTestSources (default) @ unit-testing-configuration ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ unit-testing-configuration ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile) @ unit-testing-configuration ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ unit-testing-configuration ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile) @ unit-testing-configuration ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/target/test-classes
[INFO]
[INFO] --- gmavenplus-plugin:1.5:testCompile (default) @ unit-testing-configuration ---
[INFO] Using Groovy 2.4.4 to perform testCompile.
[INFO] Compiled 1 file.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.502 s
[INFO] Finished at: 2015-08-25T20:43:11+03:00
[INFO] Final Memory: 22M/221M
[INFO] ------------------------------------------------------------------------

After we have compiled our unit tests, we have to find a way to run them with Maven.

Running Our Unit Tests

We can run our unit tests by using the Maven Surefire Plugin. Because we want to run both "normal" unit tests and unit tests that are written by using the Spock Framework, we have to configure the Maven Surefire Plugin by following these steps:

  1. Include all test classes whose name ends with the string: 'Test'. These are "normal" unit tests that are written by using the Java programming language.
  2. Include all test classes whose name ends with the string: 'Spec'. These are unit tests that are written by using the Spock Framework and the Groovy programming language.

After we have configured the Maven Surefire Plugin, the plugins section of our pom.xml file looks as follows:

<plugins>
    <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.5</version>
        <executions>
            <execution>
                <goals>
                    <goal>addTestSources</goal>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <includes>
                <include>**/*Test.java</include>
                <include>**/*Spec.java</include>
            </includes>
        </configuration>
    </plugin>
</plugins>

We can now run our unit tests by running the following command at the command prompt:

mvn clean test

When we do this, we see that the Maven Surefire Plugin runs the unit tests found from these test classes:

  • The net.petrikainulainen.spock.HelloSpec is a test class that uses Spock Framework.
  • The net.petrikainulainen.spock.HelloTest is a "normal" test class that uses JUnit.

The relevant part of the output looks as follows:

> mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Writing Unit Tests With Spock - Configuration 0.1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ unit-testing-configuration ---
[INFO] Surefire report directory: /Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.petrikainulainen.spock.HelloSpec
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.203 sec - in net.petrikainulainen.spock.HelloSpec
Running net.petrikainulainen.spock.HelloTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec - in net.petrikainulainen.spock.HelloTest

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.415 s
[INFO] Finished at: 2015-08-24T21:53:09+03:00
[INFO] Final Memory: 20M/219M
[INFO] ------------------------------------------------------------------------

The last thing that we have to do is to configure Maven to create an HTML test report that describes the test results of unit tests that use the Spock Framework.

Creating an HTML Test Report

We can create an HTML test report by using the Spock Reports Extension. By default, it creates an HTML report for each invoked specification and and a summary that lists all invoked specifications.

We can use this Spock extension by following these steps:

First, we need to add the Bintray's JCenter Maven repository into our pom.xml file. After we have done it, the repositories section of our pom.xml file looks as follows:

<repositories>
    <repository>
        <id>jcenter</id>
        <name>JCenter Repo</name>
        <url>http://jcenter.bintray.com</url>
    </repository>
</repositories>

Second, we need to add the Spock Reports Extension jar into the classpath. We can do this by declaring the spock-reports dependency (version 1.2.7) in our pom.xml file. After we have done it, the dependencies section of our pom.xml file looks as follows:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-core</artifactId>
        <version>1.0-groovy-2.4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.athaydes</groupId>
        <artifactId>spock-reports</artifactId>
        <version>1.2.7</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Third, because we use Maven, we have to change the the output directory of the Spock Reports Extension. The reason for this is that the default output directory is build/spock-reports, and we want that our HTML test report is created to the target/spock-reports directory.

We can customize the behavior of the Spock Reports Extension by creating a properties file to the following location (relative to the classpath):

META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties

We can change the output directory by following these steps:

  1. Get the default properties file.
  2. Copy the default properties file to the src/test/resources/META-INF/services/ directory.
  3. Set the value of the com.athaydes.spockframework.report.outputDir property to target/spock-reports.

The content of our properties file looks as follows:

# Name of the implementation class of the report creator
# Currently supported classes are:
#   1. com.athaydes.spockframework.report.internal.HtmlReportCreator
#   2. com.athaydes.spockframework.report.template.TemplateReportCreator
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.internal.HtmlReportCreator

# Set properties of the report creator
# For the HtmlReportCreator, the only properties available are
# (the location of the css files is relative to the classpath):
com.athaydes.spockframework.report.internal.HtmlReportCreator.featureReportCss=spock-feature-report.css
com.athaydes.spockframework.report.internal.HtmlReportCreator.summaryReportCss=spock-summary-report.css
# exclude Specs Table of Contents
com.athaydes.spockframework.report.internal.HtmlReportCreator.excludeToc=false

# Output directory (where the spock reports will be created) - relative to working directory
com.athaydes.spockframework.report.outputDir=target/spock-reports

# If set to true, hides blocks which do not have any description
com.athaydes.spockframework.report.hideEmptyBlocks=false
Additional Reading:

We can now run our unit tests by using the command:

mvn clean test

When we run our unit tests, we see that the Spock Reports Extension is initialized before our unit tests are run:

> mvn clean test

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Aug 24, 2015 10:41:41 PM org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap invoke
INFO: Configuring com.athaydes.spockframework.report.SpockReportExtension
Aug 24, 2015 10:41:41 PM org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap invoke
INFO: Trying to load custom configuration at file:/Users/loke/Projects/Java/Blog/spock-examples/unit-testing/configuration/target/test-classes/META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties
Aug 24, 2015 10:41:41 PM org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap invoke
INFO: SpockReports config loaded: [com.athaydes.spockframework.report.internal.HtmlReportCreator.excludeToc:false, com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension:md, com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile:/templateReportCreator/spec-template.md, com.athaydes.spockframework.report.IReportCreator:com.athaydes.spockframework.report.internal.HtmlReportCreator, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile:/templateReportCreator/summary-template.md, com.athaydes.spockframework.report.internal.HtmlReportCreator.summaryReportCss:spock-summary-report.css, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName:summary.md, com.athaydes.spockframework.report.internal.HtmlReportCreator.featureReportCss:spock-feature-report.css, com.athaydes.spockframework.report.hideEmptyBlocks:false, com.athaydes.spockframework.report.outputDir:target/spock-reports]
Aug 24, 2015 10:41:41 PM org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap invoke
INFO: Loading settings for reportCreator of type com.athaydes.spockframework.report.internal.HtmlReportCreator
Running net.petrikainulainen.spock.HelloSpec
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.229 sec - in net.petrikainulainen.spock.HelloSpec
Running net.petrikainulainen.spock.HelloTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in net.petrikainulainen.spock.HelloTest

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.481 s
[INFO] Finished at: 2015-08-24T22:41:42+03:00
[INFO] Final Memory: 20M/218M
[INFO] ------------------------------------------------------------------------

After we have run our unit tests, we can see the created HTML test report by opening the index.html file found from the target/spock-reports directory.

If you want to see how the HTML test report looks like, and you don't want to build the example application of this blog post, you can take look at the README of the Spock Reports Extension.

Let's summarize what we learned from this blog post.

Summary

This blog post has taught us four things:

  • We know how we can get the required dependencies with Maven.
  • We can compile Groovy code by using the GMavenPlus Plugin.
  • We can configure the Surefire Maven Plugin to run unit tests that use the Spock Framework.
  • We can create an HTML test report, which contains the test results of unit tests that use the Spock Framework, by using the Spock Reports Extension.

The next part of this tutorial describes how we can create a Gradle project that fulfils the same requirements than our Maven project.

P.S. You can get the example application of this blog post from Github.

4 comments… add one
  • jneira May 27, 2016 @ 12:16

    Hi, thanks for the detailed explanation of how to integrate spock with maven.
    I had an issue with the reporting: using the lined default properties resulted in several
    No such property: xxxx for class: com.athaydes.spockframework.report.internal.HtmlReportCreator
    I had to get the config file inside spock-report 1.2.7 and copy it to the META-INF folder to avoid them

    • Petri May 27, 2016 @ 18:47

      You are welcome! Also, thank you for reporting your problem. I wonder what could be wrong since I copied the reporting configuration file from the Spock Report 1.2.7 as well. It seems that I have test the example application and see if I can fix it.

  • Ganesh Apr 24, 2019 @ 0:37

    We have the exact same use case - Spock for Java Application - But trying to create cobertura report. We are facing java.lang.VerifyError - I have the same maven setup what mentioned above

    2019-04-23 16:35:36,885 ERROR Application startup failed
    java.lang.VerifyError: Instruction type does not match stack map
    Exception Details:
    Location:

Leave a Reply