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.