Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Groovy has excellent support for Testing with Unit Testing (GroovyTestCase adds extra capabilities to TestCase from JUnit 3.8.2) and Mocking capabilities built right in. Currently, there are no special Groovy extensions for JUnit 4 but it's easy to use so long as you are using Groovy 1.5+ and Java 5+ (a requirement for annotations/Junit 4.x). Here are some examples.

Make sure you are using at least Groovy 1.5 (we used 1.5.6) and JUnit 4.x (we used 4.4).

Simple Example

Let's test some of the built-in arithmetic operators in Groovy.

Code Block
import org.junit.Test
import static org.junit.Assert.assertEquals

class ArithmeticTest {
    @Test
    void additionIsWorking() {
        assertEquals 4, 2+2
    }

    @Test(expected=ArithmeticException)
    void divideByZero() {
        println 1/0
    }
}

Alternatively, one could use the shouldFail method as follows:

Code Block
class ArithmeticTest {
    final shouldFail = new GroovyTestCase().&shouldFail

    @Test
    void divideByZero() {
        shouldFail(ArithmeticException) {
            println 1/0
        }
    }
}

Our test class includes two tests additionIsWorking and divideByZero. The second of these is expected to fail with an ArithmeticException exception.

Running the test gives:

Code Block
JUnit version 4.4
..
Time: 0.078

OK (2 tests)

Hamcrest Matching

You can use the Hamcrest matchers that come with JUnit 4.4 and above like this:

Code Block
import static org.junit.Assert.assertThat
import static org.hamcrest.CoreMatchers.*
import static org.junit.matchers.JUnitMatchers.*
import org.junit.Test

class LanguageTest {
    def languages = [tom:['Java', 'Groovy'], dick:['C#', 'Ruby']]

    @Test void tomKnowsJavaAndGroovyHamcrest() {
        assertThat languages['tom'], is(["Java", "Groovy"])
        assertThat languages['tom'][0], containsString("v")
        assertThat languages['tom'][1], containsString("v")
    }

    @Test void tomKnowsJavaAndGroovyNative() {
        assert languages['tom'] == ["Java", "Groovy"]
        assert languages['tom'].every{ it.contains("v") }
    }
}

The first test uses the matchers. You can see by the second test, that native Groovy assertions are usually going to do the job just as well if not better in the Groovy world.

Parameterized Testing

JUnit 4.x includes the ability to have parameterized tests. Suppose we want to test the following program:

Code Block
class GroovyMultiplier {
    int triple(int val) {
        return val * 3
    }
}

Here is what your code might look like. This example uses parameterization.

Code Block
import org.junit.Test
import org.junit.Before
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters

@RunWith(Parameterized)
class MultiplierTest {
    def testee
    def param
    def expectedResult

    @Parameters static data() {
          return (2..4).collect{ [it, it * 3] as Integer[] }
    }

    MultiplierTest(a, b) {
        param = a
        expectedResult = b
    }

    @Before void setUp() {
        testee = new GroovyMultiplier()
    }

    @Test void positivesFixed() {
        assert testee.triple(1) == 3: "+ve multiplier error"
    }

    @Test void positivesParameterized() {
        assert testee.triple(param) == expectedResult
    }

    @Test void negativesParameterized() {
        assert testee.triple(-param) == -expectedResult
    }
}

The output will look something like this:

Code Block
JUnit version 4.4
............
Time: 0.062

OK (9 tests)

Theory Tests

You can use the experimental Theory tests from JUnit 4.4 and above as follows:

Code Block
import org.junit.runner.*
import org.junit.experimental.theories.*
import static org.junit.Assume.assumeTrue as assume

@RunWith(Theories)
class LanguageTheoryTest {
    @DataPoint public static String java = 'Java'
    @DataPoint public static String ruby = 'JRuby'
    @DataPoint public static String python = 'Jython'
    @DataPoint public static String javascript = 'Rhino'
    @DataPoint public static String groovy = 'Groovy'
    @DataPoint public static String scala = 'Scala'
    @DataPoint public static String csharp = 'C#'

    def jvmLanguages = [java, ruby, python, groovy, scala, javascript]

    def teamSkills = [
        tom:   [java, groovy, ruby],
        dick:  [csharp, scala, java, python],

        harry: [javascript, groovy, java]
    ]

    @Theory void everyone_knows_java() {
        teamSkills.each { person, skills ->
            assert java in skills
        }
    }

    @Theory void someone_knows_each_jvm_language(String language) {
        assume language in jvmLanguages
        assert teamSkills.any { person, skills ->
            language in skills
        }
    }

    @Theory void tom_knows_all_languages_ending_with_y(String language) {
        assume language.endsWith('y')
        assert language in teamSkills.tom
    }
}

When run, this gives:

Code Block
JUnit version 4.4
...
Time: 0.063

OK (3 tests)