One of my clients had to use Groovy scripts to synchronize thousands of user identities between multiple data sources. When I started working on the project the development process looked similar to this:

groovy-maven-junit-1

It's obvious that this process was far from being efficient. It was very time consuming and, most importantly, errors were caught too late in the development cycle making them very expensive to fix.

Over the years, I've learned to ask myself the following question over and over again: what can I do to make this process more efficient? The answer in this case was simple:

Test earlier. Test better.

So I decided to introduce a new testing phase earlier in the process:

groovy-maven-junit-2

I had to tackle some problems along the way so I decided to write a blog post about it.

Pre-requisites

For this example we will be using the following components:

The source code for the sample maven project is available on github.

Project Dependencies

First, you need to add the following dependencies to your pom.xml:

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

Then, we need to instruct maven to compile our Groovy source files (if any) and run the JUnit test cases during the build process. The only thing we need to do is add the gmaven-plugin to the pom.xml as follows:

<plugin>
   <groupId>org.codehaus.gmaven</groupId>
   <artifactId>gmaven-plugin</artifactId>
   <version>1.5</version>
   <executions>
   	<execution>
            <configuration>
		<providerSelection>2.0</providerSelection>
	    </configuration>
	    <goals>
	        <goal>generateStubs</goal>
		<goal>compile</goal>
		<goal>generateTestStubs</goal>
		<goal>testCompile</goal>
	    </goals>
	</execution>
    </executions>
</plugin>

By default, the plugin expects all the Groovy source files to be located under "src/main/groovy" and the Groovy test files under "src/test/groovy".

Sample Project

Our sample application consists of a single Groovy source file named "MyGroovyClass.groovy". This file contains the class (MyGroovyClass) that we want to test.

screenshot1

I decided to add two different flavors of the same test, one for each JUnit version, to clarify the differences between the two. When using JUnit 3 you have to extend GroovyTestCase which, besides telling Groovy to run the class as a test, it also offers additional functionality, such as assertion methods, that will come in handy when writing your tests. Here are the contents of MyGroovyClassJUnit3Test.groovy:

import MyGroovyClass
class MyGroovyClassJunit3Test extends GroovyTestCase {

    void setUp() {
        println "Inside setup()"
    }

    void test1() {
        println "Running test 1"
        MyGroovyClass my = MyGroovyClass.newInstance()
        assertEquals("Hello", my.method1())
    }

    void test2() {
        println "Running test 2"
        MyGroovyClass my = MyGroovyClass.newInstance()
        assertEquals("Bye", my.method2())
    }

    void tearDown() {
        println "Inside tearDown()"
    }
}

Take a look at the GroovyTestCase API docs for a detailed explanation of all the assertion methods.

If you decide to use JUnit 4, you can directly use standard JUnit annotations (@Before, @After, @Test, etc...). However, you'll have to import GroovyAssert to use assertion methods in your tests:

import org.junit.*
import MyGroovyClass
import static groovy.test.GroovyAssert.*

class MyGroovyClassJunit4Test {

    @BeforeClass
    static void setUpBeforeClass() {
        println "Inside setUpBeforeClass()"
    }

    @Before
    void setUp() {
        println "Inside setUp()"
    }

    @Test
    void myTest1() {
        println "Running test 1"
        MyGroovyClass my = MyGroovyClass.newInstance() 
        assertEquals("Hello", my.method1())
    }

    @Test
    void myTest2() {
        println "Running test 2"
        MyGroovyClass my = MyGroovyClass.newInstance()
        assertEquals("Bye", my.method2())
    }

    @After
    void tearDown() {
        println "Inside tearDown()"
    }

    @AfterClass
    static void tearDownAfterClass() {
        println "Inside tearDownAfterClass()"
    }
}

Another thing to notice is that JUnit 4 lets you use the @BeforeClass and @AfterClass annotations so that you can execute some code before and after all the tests in the class have been run (this feature is not supported in JUnit 3). This is different than using the @Before and @After annotations (or the equivalent setUp() and tearDown() methods in JUnit 3). The methods annotated with @Before and @After will execute after each test is run.

Run the Test Cases

To execute all the test cases run the following maven command:

mvn clean package

You should see an output similar to this:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running MyGroovyClassJunit3Test Inside setup() Running test 1 Inside tearDown() Inside setup() Running test 2 Inside tearDown() Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.412 sec Running MyGroovyClassJunit4Test Inside setUpBeforeClass() Inside setUp() Running test 1 Inside tearDown() Inside setUp() Running test 2 Inside tearDown() Inside tearDownAfterClass() Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.05 sec Results : Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

You can also run individual test cases by passing the test name as a maven property:

```
mvn clean test -Dtest=MyGroovyClassJunit3Test
```

## **Final Notes**

Regular Java classes can also be tested from your Groovy test files. Just place you classes in "_src/main/java_" as usual and import them in your Groovy test classes. Take a look at the following examples for more details about how to test Java classes: _MyJavaClassJunit3Test.groovy_ and _MyJavaClassJunit4Test.groovy_.

The _GroovyAssert_ class implementation was first added to Groovy 2.3. So if you are using Groovy 2.2 or older you will have to import _org.junit.Assert_ directly to obtain similar results.