Marcin Erdmann

Groovy, Grails, Geb...

Setting system properties for JUnit run configurations in Intellij using Gradle

There is one particular Gradle feature that I couldn't live without - IDE project generation. Firstly it means that there are no more IDE specific files in your repository. Secondly it is a perfect tool to easily and quickly generate IDE project configuration files in a repeatable and customisable manner.

There are currently two IDE plugins that gradle ships with Eclipse plugin and IDEA plugin. In this post I will describe how to use the latter to customise the generated project configuration files for IntelliJ.

There are three types of Intellij project configuration files - project files (.ipr), module files (.iml) and workspace files (.iws). While Gradle provides a DSL for modyfing those files (at least for project and module files) quite often you will have to revert to using withXml {} hook to do non-standard stuff. It means dealing with those large XML configuration files and understanding their syntax which is not the nicest of tasks but it's worth it.

My use case came from preparing for my "Test driving Gaelyk applications" talk from GGX and Greach. I noticed that when running the tests the console output contained way more logging than I would be happy with. The logging came from the appengine-testing module which is used by Gaelyk Spock Helpers I was showcasing. I needed to change configuration of java.utils.logging to limit the amount of logging produced.

One of the ways of specifying where java.utils.logging config file is located is to use java.util.logging.config.file system property. I knew that I wanted it to be specified for all JUnit run configurations in IntelliJ so I had a look at the .iws file to learn how the default JUnit run configuration part looks like:

<project version="4">
    ...
    <component name="RunManager">
        ...
        <configuration default="true" type="JUnit" factoryName="JUnit">
            ...
            <option name="VM_PARAMETERS" value="" />
            ...
        </configuration>
        ...
    </component>
    ...
</project>

After finding it I knew that I have to modify the VM_PARAMETERS option and that can be done using the idea.workspace.iws.withXml {} hook by simply adding the following to my build.gradle:

idea.workspace.iws.withXml { provider ->
    def node = provider.asNode()
    def runManager = node.component.find { it.'@name' == 'RunManager' }
    def defaultJUnitConf = runManager.configuration.find { it.'@default' == 'true' && it.'@type' == 'JUnit' }
    def vmParametersOption = defaultJUnitConf.option.find { it.'@name' == 'VM_PARAMETERS' }
    vmParametersOption.'@value' = '-Djava.util.logging.config.file=logging.properties'
}

Then all that I needed to to is regenerate the idea files of my project by running gradle idea and reloading the project in the IDE. From then on all the newly created JUnit run configurations had the system property set.

There are other situations where you might want to modify IDE project configuration files. For example to tell IntelliJ that the code is versioned using git so that you don't have to manually do it after you check it out for the first time on a new machine and generete config files for it you would add the following:

idea.project.ipr.withXml { provider ->
    def node = provider.asNode()
    node.component.find { it.'@name' == 'VcsDirectoryMappings' }?.mapping[0].'@vcs' = 'Git'
}

The possibilities here are endless. For example Geb project configures code style settings as well as adds a licence header to all newly created files.