Fun with Gradle Plugins – Integration Tests

Currently in the process of migrating a 10000 line Ant build to Gradle. Not quite as fun as it sounds, but at least the Gradle build should be faster, more maintainable and hopefully free from cruft.

One of this build’s peculiarities is that it executes Unit Tests and Integration Tests at different points in the build cycle. The Integration tests rely on nasty things like databases, IBM MQ and LDAP. Things that are difficult to mock out & slow your build down to a grind if you execute these tests too frequently. Some of them are really System tests, if you’re being pedantic, but let’s just ignore that. The point is, there’s a category of tests that we don’t want to see executed during the normal unit test execution.

Full code available on GitHub.

Selim Ă–ber explains how to accomplish this on his blog. I wanted to see if I could turn it into a plugin instead, as it will have to be applied to many different projects (made more difficult by a heterogenous coding environment. Not everything is a Java project).

The Goal

The goal of this plugin is to be able to execute tests in src/integration/java by executing the integrationTest target. These tests will expressly not be executed during the normal build cycle. These are to be run manually (or by your CI engine or whatever) periodically, as opposed to continuously on each build.

buildSrc

The buildSrc folder is Gradle’s magic box. It lives in your project root and contains — as the name might imply — some of your build’s source code. Gradle is smart enough to pick up on the stuff there, and will automagically compile it when it changes.

I chose groovy for this plugin, so I’ll just let Gradle know about that, and I’ll politely ask it to make the Gradle API available for me to use.

buildSrc/build.gradle

apply plugin: 'groovy'
 
repositories {
	mavenCentral()
}
 
dependencies {
	compile gradleApi()
}

Next is the actual plugin.

buildSrc/src/main/groovy/org/lick/me/gradle/IntegrationTestPlugin.groovy

package org.lick.me.gradle
 
import org.gradle.api.Plugin
 
import org.gradle.api.Project
import org.gradle.api.tasks.testing.Test
 
/**
 * Applying this plugin will let gradle know that the project contains integration tests.
 * These can be executed at a later point in time than unit tests -- when a database etc 
 * become available. 
 */
class IntegrationTestPlugin implements Plugin<Project> {
	@Override
	void apply(final Project project) {
 
		project.sourceSets {
			integTest {
				java.srcDir project.file('src/integration/java')
				resources.srcDir project.file('src/integration/resources')
			}
		}
 
		project.dependencies {
			integTestCompile project.sourceSets.main.output
			integTestCompile project.configurations.testCompile
			integTestCompile project.sourceSets.test.output
			integTestRuntime project.configurations.testRuntime
		}
 
		project.task('integrationTest', type: Test, description: 'Runs the integration tests.', group: 'Verification') {
			testClassesDir = project.sourceSets.integTest.output.classesDir
			classpath = project.sourceSets.integTest.runtimeClasspath
		}
 
		project.task('allTests', dependsOn: [project.test, project.integrationTest], description: 'Runs all tests.', group: 'Verification') {
 
		}
	}
}

Now all we need is a bit of magic to let Gradle know that we want to be able apply this plugin in other projects.

buildSrc/src/main/resources/META-INF/gradle-plugins/integrationTests.properties

implementation-class=org.lick.me.gradle.IntegrationTestPlugin

Now we can add the plugin to your projects.

apply plugin: 'integrationTests'

Running gradle tasks will now result in two extra tasks in the Verification section.

tasks

Leave a Reply

Your email address will not be published. Required fields are marked *