How to use GINT for unit testing

Summary

GINT was built to solve integration test requirements. However, it can also be used for unit testing of Java and Groovy code. In general, Groovy is much more efficient to write unit tests over standard Java based JUnit tests. Groovy unit testing describes the advantages of using Groovy in a JUnit context. Using GINT for unit testing has similar advantages plus some other characteristics that make it another good alternative particularly if you use GINT for integration testing.

Key Groovy and GINT advantages over Java based testing:

  1. Groovy test assertions - additional test assertions
  2. Groovy power asserts - makes it easy to debug failures
  3. Groovy test can fit into existing compile and run scenarios like Maven and Eclipse - this is more difficult for GINT tests
  4. Run test from a command line
  5. GINT makes it easy to run single tests, specific list of tests, groups of tests, or last failed
  6. GINT test run directly without any compile step improving test development turn-around time
  7. GINT testcases can be easily generated by code
    • Allows for finer grain testcases - one per assert
  8. GINT testcases are less verbose
  9. GINT has no dependencies on JUnit

Usage

GINT

Example runs

Code

This is a unit test for GINT helper functions included with the GINT source.

import org.swift.tools.Helper        // test static functions
includeTool << org.swift.tools.Gint  // test framework

def stringToQuoted = [   // map strings to their single quoted value
    "x"    : "'x'",
    "x'y"  : "'x''y'",
    "x''y" : "'x''''y'",
    "x\"y" : "'x\"y'",
    "'x'y" : "'''x''y'",
    "x'y''": "'x''y'''''",
    "'xy'" : "'''xy'''",
]
def separatedString = "x, x'y, x''y, x\"y, 'x'y, x'y'', 'xy'" // expected result for comma separating all the strings in stringQuoted map

gint.initialize(this)

stringToQuoted.each { string, quoted ->
    gint.add([name: 'quoteString_' + string, inline: { assert quoted == Helper.quoteString(string) } ])
    gint.add([name: 'stripQuote_' + string, inline: { assert string == Helper.stripQuotes(quoted, "'") } ])
    // verify stripQuote leaves unquoted strings alone
    if (!string.startsWith("'") || !string.endsWith("'")) {  // not already quoted
        gint.add([name: 'leaveAlone_' + string, inline: { assert string == Helper.stripQuotes(string) } ])
    }
}

gint.add('separatedString', [
    [name: 'listToSeparatedString', inline: { assert separatedString == Helper.listToSeparatedString(stringToQuoted.keySet(), ", ") } ],
    [name: 'listToSeparatedStringEmpty', inline: { assert "" == Helper.listToSeparatedString([], ',') } ],
])

gint.add([name: 'getProcessName', inline: { assert Helper.getProcessName().find(~/\d{2}/) != null } ]) // at least 2 digits should be returned

gint.finalizeTest() // final preparations for running tests

GroovyTestCase

Equivalent test using GroovyTestCase also included with GINT source. Note that multiple asserts have to be grouped into each testcase in order to generate the asserts efficiently.

package org.swift.tools

class HelperTest extends GroovyTestCase {

    def stringToQuoted = [   // map strings to their single quoted value
        "x"    : "'x'",
        "x'y"  : "'x''y'",
        "x''y" : "'x''''y'",
        "x\"y" : "'x\"y'",
        "'x'y" : "'''x''y'",
        "x'y''": "'x''y'''''",
        "'xy'" : "'''xy'''",
    ]
    def separatedString = "x, x'y, x''y, x\"y, 'x'y, x'y'', 'xy'" // expected result for comma separating all the strings in stringQuoted map

    public void testQuoteString() {
        stringToQuoted.each { string, quoted ->
            assert quoted == Helper.quoteString(string)
        }
    }

    public void testStripQuotes() {
        stringToQuoted.each { string, quoted ->
            assert string == Helper.stripQuotes(quoted, "'")
        }
    }

    // Verify unquoted strings are left alone
    public void testStripQuotesLeaveAlone() {
        stringToQuoted.each { string, quoted ->
            if (!string.startsWith("'") || !string.endsWith("'")) {  // not already quoted
                assert string == Helper.stripQuotes(string, "'")
            }
        }
    }

    public void testListToSeparatedString() {
        assert separatedString == Helper.listToSeparatedString(stringToQuoted.keySet(), ", ");
    }

    public void testListToSeparatedStringEmpty() {
        assert "" == Helper.listToSeparatedString([], ',')
    }

    public void testGetProcessName() {
        assert Helper.getProcessName().find(~/\d{2}/) != null // at least 2 digits should be returned
    }
}

Test development scenario

  1. Develop test
  2. Run - all tests by default
    gant -f helperTest2.gant
    
     = = = = = = = = = =  helpertest2 started at Fri Sep 10 15:33:13 CDT 2010  = = = = = = = = = =
    
    ...
    
        [start] listToSeparatedString
        [error] Assertion failed: 
    
    assert separatedString == Helper.listToSeparatedString(stringToQuoted.keySet(), ",")
           |               |         |                     |              |
           |               false     |                     |              [x, x'y, x''y, x"y, 'x'y, x'y'', 'xy']
           |                         |                     {x='x', x'y='x''y', x''y='x''''y', x"y='x"y', 'x'y='''x''y', x'y''='x''y''''', 'xy'='''xy'''}
           |                         x,x'y,x''y,x"y,'x'y,x'y'','xy'
           x, x'y, x''y, x"y, 'x'y, x'y'', 'xy'
       [failed] listToSeparatedString: Expected 0 but got -98
     [complete] listToSeparatedString - 0.012 secs
    
    ...
    
         [info] Failure summary:
       [failed] listToSeparatedString: Expected 0 but got -98
    
         [info] Failed testcases  . . . . . . . . . . . . : 1    <<< TEST FAILED
         [info] Successful testcases  . . . . . . . . . . : 22
         [info] Total testcases . . . . . . . . . . . . . : 23
         [info] Elapsed run time  . . . . . . . . . . . . : 0.828 secs
    
     = = = = = = = = = =  helpertest2 completed at Fri Sep 10 15:33:13 CDT 2010  = = = = = = = = = =
    
    : Test failed.
    
    BUILD FAILED
    Total time: 2.02 seconds
    
  3. Fix error in code!
  4. Run - note only failed tests runs by default
    gant -f helperTest2.gant
    
     = = = = = = = = = =  helpertest2 started at Fri Sep 10 15:36:24 CDT 2010  = = = = = = = = = =
    
         [info] Run last failed testcases: listToSeparatedString
        [start] listToSeparatedString
       [ending] listToSeparatedString
     [complete] listToSeparatedString - 0.032 secs
    
         [info] Successful testcases  . . . . . . . . . . : 1    <<< TEST SUCCESSFUL
         [info] Not run testcases . . . . . . . . . . . . : 22
         [info] Total testcases . . . . . . . . . . . . . : 23
         [info] Elapsed run time  . . . . . . . . . . . . : 0.75 secs
    
     = = = = = = = = = =  helpertest2 completed at Fri Sep 10 15:36:24 CDT 2010  = = = = = = = = = =
    
    
    BUILD SUCCESSFUL
    Total time: 1.78 seconds
    
  5. Run again - to verify all are successful
    gant -f helperTest2.gant
    
     = = = = = = = = = =  helpertest2 started at Fri Sep 10 15:38:31 CDT 2010  = = = = = = = = = =
    
    ...
    
         [info] Successful testcases  . . . . . . . . . . : 23    <<< TEST SUCCESSFUL
         [info] Total testcases . . . . . . . . . . . . . : 23
         [info] Elapsed run time  . . . . . . . . . . . . : 0.886 secs
    
     = = = = = = = = = =  helpertest2 completed at Fri Sep 10 15:38:31 CDT 2010  = = = = = = = = = =
    
    BUILD SUCCESSFUL
    Total time: 2.02 seconds