Marcin Erdmann

Groovy, Grails, Geb...

Gaelyk Guice Plugin released!

I'm happy to announce that Gaelyk Guice Plugin has just landed in Maven Central.

The plugin uses Guice to provide a dependency injection mechanism for Gaelyk applications. Basically it makes it as easy to inject dependencies in Gaelyk groovlets as:

injectDependencies MyService

assert myService instanceof MyService

If you wish to have a look at the documentation or the source code to learn about all of the features and see more examples you can do so on Github.

Gaelyk Functional Test Tools released!

I'm happy to announce the first public release of Gaelyk Functional Test Tools. It is available in Maven Central.

The library is simply a set of tools that should simplify some common tasks when functional testing Gaelyk applications. It is also an integration point for Gaelyk Remote Control, Geb and Spock. Currently the library provides:

  • own RemoteControl class that determines the remote control url based on conventions so that you don't have to specify one all the time
  • @ModifiesDatastore Spock extension that allows to wipe out datastore after running certain features
  • a simple DSL for setting up data in the datastore if your feature needs a certain data state to run
  • loginTo method that allows to go to a Geb Page after logging into the application using default GAE authentication

Documentation is available here and source code is here.

Gaelyk Remote Control released!

I'm happy to announce the first public release of Gaelyk Remote Control. It is available in Maven Central.

It's main usage is to setup a Gaelyk application for functional tests by allowing to execute closures defined in tests on the server. The library is based on, and depends on, Groovy Remote Control with only two differences:

  • Gaelyk specific variables are available in remote context - all the GAE-specific variables from this list are bound into context of remote closures. Thanks to that you can use the same property names to access the variables that are also available in your Gaelyk views and controllers.
  • Exceptions thrown in remote are properly handled - by default the original version of groovy remote sanitizes exceptions thrown on the remote before sending them over to the client. To achieve that it uses classes that are restricted in GAE which meant SecurityExceptions were being thrown. The library addressed this problem by simply sending full stacktraces over to the client.

For more information please refer to the project documentation on github.

My Gradle init script

Recently I started using Gradle more and more to initialize my test/example projects. The main advantage of doing so is the fact that Gradle allows you to manage dependencies of your project easily. So if for example you want to give some new library a go it's extremely easy to get it from maven central with Gradle. And thanks to Gradle's idea and eclipse plugins it's so easy to import the project with all the dependencies set up to your favourite IDE.

Two things I found myself doing all the time when initializing a new project was adding Gradle wrapper and manually initializing source directories. Some time ago Guillaume Laforge wrote a blog post that contains a wrapper task and a directory initialization task but one would still need to copy it into build.gradle when creating a new project - that's not automated enough!

Last week I watched Luke Daley's Gradle webinar on standardizing build environment and learned the concept of init scripts from it. Now I know that if I put the following in my ~/.gradle/init.gradle I will get the wrapper, directory initialization and idea plugin's tasks in all of my builds for free:

projectsEvaluated {
    rootProject.allprojects {
        apply plugin: 'idea'

        if (!tasks.findByName('initSourceDirs')) {
            task initSourceDirs(description : 'make all dirs for project setup') << { task ->
                def language = System.properties["${task.name}.only"] ?: 'allSource'
                sourceSets.all { 
                    it["${language}"].srcDirs.each { it.mkdirs() }   
                }   
            }   
        }   

        if (!tasks.findByName('wrapper') && !parent) {
            task wrapper(type: Wrapper) {
                gradleVersion = '1.2'
            }   
        }   
    }
}

rootProject {
    apply {
        plugin 'build-announcements'
    }       
}

Note that the tasks are added to the project only if the project doesn't define tasks with the exact same names. Applying a plugin is idempotent in Gradle so it doesn't need to be guarded by an if statement. You can also easily limit which source set types directories will be created using initSourceDirs.only system property. By default directories for all source sets (main, test, ...) and all source set types (java, resources, groovy, ...) will be generated so if your project defines an additional source sets, i.e. functionalTest, it will be picked up as well.

I also decided to apply build-announcements plugin to all of my projects which sends a desktop notification (notify-send for my OS) every time a build has finished with either a success and a failure. So if I have a long running build I can switch to doing something else instead of waiting for it to finish and I can come back to it as soon as it's done as I will be notified about the build completion.

So now to get a brand new Groovy, Gradle backed, project imported into IntelliJ I only need to create a short and simple build.gradle:

apply plugin: 'groovy'

repositories {
    mavenCentral()
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.8.6'
}

And then execute the following commands:

  • gradle wrapper
  • ./gradlew initSourceDirs -DinitSourceDirs.only=groovy
  • ./gradlew idea

Gradle's check task

One of the things I completely missed when I was learning Gradle was the check task that is added to your project when you apply java plugin to it. This is a pretty useful task and I really like the convention behind it.

The documentation of the task says that it depends on "all verification tasks in the project, including test. Some plugins add additional verification tasks to the project". That is the case for example for codenarc plugin which adds dependencies on its tasks to the check task. Thanks to that when executing check task both your tests and CodeNarc verifications will be run.

I also applied that convention when I added gaeFunctionalTest task to Gradle GAE plugin - so running check task will execute both your unit and functional tests.

You should also always add a dependency to check task on any of your new tasks that verify your project.