Integrating Gatling Into a Gradle Build: Understanding SourceSets and Configuration
Gradle sourceSets are logical groupings of related files. Configurations are groupings of related dependencies. Using both, we can create some neat build configurations.
Join the DZone community and get the full member experience.
Join For FreeI recently worked on a project where we had to integrate the excellent load testing tool Gatling into a Gradle-based build. There are Gradle plugins available which make this easy, two of them being this and this, however for most needs, a simple execution of the command line tool itself suffices, so this post will go into some details of how Gatling can be hooked up into a Gradle build and in the process understand some good gradle concepts.
SourceSets and Configuration
To execute the Gatling CLI, I need a location for the source code and related content of the Gatling simulations, and I need a way to get the Gatling libraries. This is where two concepts of Gradle (sourceSets and Configuration) come into play.
Let us start with the first one - sourceSets.
sourceSets
sourceSets are simply a logical grouping of related files and are best demonstrated with an example. If I were to add a "java" plugin to a Gradle build:
apply plugin: 'java'
The sourceSets property would now show up with two values: "main" and "test," and if I wanted to find details of the these sourceSets, a Gradle task can be used for printing the details:
task sourceSetDetails {
doLast {
sourceSets {
main {
println java.properties
println resources.properties
}
test {
println java.properties
println resources.properties
}
}
}
}
Coming back to Gatling, I can essentially create a new sourceSet to hold the Gatling simulations:
sourceSets {
simulations
}
This would now expect the Gatling simulations to reside in "src/simulations/java" and the resources related to it in "src/simulations/resources" folders, which is okay, but ideally I would want to keep it totally separate from the project sources. I would want my folder structure to be with load simulations in "simulations/load" and resources in "simulations/resources" folder. This can be tweaked by first applying the "scala" plugin, which brings in Scala compilation support to the project and then modifying the "simulations" sourceSet along these lines:
apply plugin: 'scala'
sourceSets {
simulations {
scala {
srcDirs = ['simulations/load']
}
resources {
srcDirs = ['simulations/resources']
}
}
}
With these set of changes, I can now put my simulations in the right place, but the dependency of Gatling and scala has not been pulled in, this is where the "configuration" feature of Gradle comes in.
Configuration
Gradle Configuration is a way of grouping related dependencies together. If I were to print the existing set of configurations using a task:
task showConfigurations {
doLast {
configurations.all { conf -> println(conf) }
}
}
These show up:
configuration ':archives'
configuration ':compile'
configuration ':compileClasspath'
configuration ':compileOnly'
configuration ':default'
configuration ':runtime'
configuration ':simulationsCompile'
configuration ':simulationsCompileClasspath'
configuration ':simulationsCompileOnly'
configuration ':simulationsRuntime'
configuration ':testCompile'
configuration ':testCompileClasspath'
configuration ':testCompileOnly'
configuration ':testRuntime'
configuration ':zinc'
"compile" and "testCompile" should be familiar ones; that is where a normal source dependency and a test dependency are typically declared like this:
dependencies {
compile 'org.slf4j:slf4j-api:1.7.21'
testCompile 'junit:junit:4.12'
}
However, it also looks like there is now configuration for "simulations" sourceSet available - "simulationsCompile" and "simulationsRuntime," etc, so with this I can declare the dependencies required for my Gatling simulations using these configurations. However, my intention is to declare a custom configuration just to go over the concept a little more, so let us explicitly declare one:
configurations {
gatling
}
And use this configuration for declaring the dependencies of Gatling:
dependencies {
gatling 'org.scala-lang:scala-library:2.11.8'
gatling 'io.gatling.highcharts:gatling-charts-highcharts:2.2.5'
}
Almost there. Now, how do we tell the sources in simulations source set to use dependency from Gatling configuration? By tweaking the sourceSet a little:
sourceSets {
simulations {
scala {
srcDirs = ['simulations/load']
}
resources {
srcDirs = ['simulations/resources']
}
compileClasspath += configurations.gatling
}
}
Running a Gatling Scenario
With the sourceSets and the configuration defined, all we need to do is to write a task to run a Gatling simulation, which can be along these lines:
task gatlingRun(type: JavaExec) {
description = 'Run gatling tests'
new File("${buildDir}/reports/gatling").mkdirs()
classpath = sourceSets.simulations.runtimeClasspath + configurations.gatling
main = "io.gatling.app.Gatling"
args = ['-s', 'simulations.SimpleSimulation',
'-sf', 'simulations/resources',
'-df', 'simulations/resources',
'-rf', "${buildDir}/reports/gatling"
]
}
See how the compiled sources of the simulations and the dependencies from the Gatling configuration is being set as the classpath for the "JavaExec" task.
A good way to review this would be to look at a complete working sample that I have here in my github repo.
Published at DZone with permission of Biju Kunjummen, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments