Fork me on GitHub

17 Jan 2010

A Gradle build for Grails plugins with test apps

There's a fairly popular technique in Grails plugin development where the plugin has 'test apps' stored in test/projects/*, each of which references the plugin by including grails.plugin.location."my-plugin" = "../../.." in its BuildConfig.groovy. Doing this allows you as a plugin developer to:
  • Automate tests for sample projects using the plugin with significantly different configurations.
  • Test using domain classes, controllers, etc. that shouldn't be packaged with the plugin.
  • Test drive, changing code in both the test app and the plugin without the need to use grails package-plugin or grails install-plugin to pick up changes.
The downside is that to run all the plugin project's tests it's necessary to run the plugin's own tests, then change directory into each of the test apps and run their tests. Continuous integration config is also fiddlier for the same reason.

I wanted to find a way to automate this so I could run all my plugins' tests with a single command. I could write a bash script or an Ant build I guess, or even use maven <shudder>. However keeping things in Groovy-land I decided to try using Gradle which I've been meaning to look into for a while now. I saw Hans Dockter's presentation on Gradle at the London Groovy & Grails Exchange back in December and was impressed with how terse and expressive the syntax is, especially compared to XML based formats. Unfortunately one thing Gradle doesn't grok yet is Grails.

The solution I've come up with is based on a post by Helmut Denk on the gradle-user list. Gradle just uses Ant's exec task to shell out and execute the appropriate Grails command. Combining this with Gradle's multi-project build support I now have plugin builds that can be run with gradle test that will automatically descend into the test apps under test/projects/*.

The build.gradle file at the root of the project defines clean and test tasks: The test task will run the plugin's unit tests. The clean task is defined just once for all projects as there's no difference in how it is done - a nice examply of Gradle's DRY-ness.

Then in settings.gradle I tell Gradle where to find the various sub-projects:
Finally each test app has it's own build.gradle that defines its test task: This is only necessary if the test apps run tests differently to the plugin - here my app is running integration rather than unit tests - otherwise I could have defined test in the same DRY manner as clean.

The process is not as fast as it could be if Grails were wired in to Gradle properly. gradle clean test for the Springcache plugin and its two test apps takes just over 2 minutes on my MBP. Also, my Gradle-fu leaves a lot to be desired right now so I'm sure there are improvements that could be made with the way I'm handling the sub-projects. But, for the purposes of a pre-commit test run or Hudson build this works pretty well.

4 comments:

Rob said...

Worth noting that to get all the usual Grails output you just need to use 'gradle -i' as Gradle is quite quiet with its output by default.

wsxwhx673 said...
This comment has been removed by a blog administrator.
Rob said...

Peter Ledbrook just posted about using a proper Gradle plugin to build Grails projects. See http://www.cacoethes.co.uk/blog/groovyandgrails/building-a-grails-project-with-gradle.

ogourment said...

Say you wanted to use the code-coverage plugin to generate cobertura reports; would these test be included in the report? Probably not...