bits and pieces

January 8, 2011

Grails: Custom Clean-up During Testing Using Build Events

Filed under: Uncategorized — Tags: , — roshandawrani @ 12:39 pm

For integration and functional tests, Grails ensures that each test gets a clean database and is not affected by the data changes made in other tests. Grails achieves it by executing each test within a transaction and rolling it back after the test is executed – so no commits actually make way to the database, effectively giving every test a clean slate.

But, what if your requirements differ from those in a standard Grails app – what if the database you want to use in your Grails application does not support transactions, or what if you want to do some non-DB clean-up before each test – then Grails mechanism does not work and it becomes your responsibility to do the clean-up, as you want.

Coming up with clean-up logic is fine, but the real question is, how to plug it in?

1) One way would be to change each of your test case and pollute it as below:

package foo

class MyControllerIntTests extends GroovyTestCase
{
    void setUp()
    {
        super.setUp()
        MyDataCleaner.resetData() /* apply the data clean-up logic */
    }
    
    void testA() { .... }       

    void testB() { .... }       
}

The above approach works, but soon becomes a maintenance headache, because for each new test case, you now have to remember to make this customary clean-up call.

2) Another approach would be to introduce a base class and make the clean-up call in its setUp(), as below:

package foo

class MyBaseIntTests extends GroovyTestCase
{
    void setUp()
    {
        super.setUp()
        MyDataCleaner.resetData() /* apply the data clean-up logic */
    }
    ...
    ...
}

class MyControllerIntTests extends MyBaseIntTests
{
    void setUp()
    {
        super.setUp()
    }
    
    void testA() { .... }       

    void testB() { .... }       
}

But this approach comes with its own issues as your tests may have to extend other special classes like grails.plugin.spock.IntegrationSpec, if your integration tests are Spock based or grails.plugin.geb.GebSpec, if you are functional tests are Geb based – you can’t easily introduce a common base class if your tests have a useful mix of such frameworks.

3) A much cleaner option is to hook into build events fired by Grails framework. Grails fires following testing related events that can be utilized for our clean-up purposes:

  • TestPhaseStart
  • TestCaseStart
  • TestStart
  • TestEnd
  • TestCaseEnd
  • TestPhaseEnd

The following piece of code can be put in _Events.groovy to hook into the events of interest and invoke the data clean-up logic.

boolean inIntegrationTestPhase = false

eventTestPhaseStart = { name ->
    inIntegrationTestPhase = (name == 'integration')
}

// reset the data in app DB
eventTestStart = { name ->
    if(inIntegrationTestPhase) {
        println "------------ Cleaning data before running the test '$name' ------------"
        MyDataCleaner.resetData()
    }
}

Now no need to maintain individual data clean-up calls from each test case, or to pollute the test cases’ inheritance hierarchy – just pick and choose when you want your data to be cleaned and do it in a transparent manner.

The Silver is the New Black Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: