I've created a Scala and Gatling project with which I want to perform some load test. The idea is that I build an executable jar, which I then simply execute to run said load test.
I have so far no problems running the load test in my IDE. However, when I try to assemble it with:
gradle assemble
The jar is empty i.e. contains my utility classes from src/main/scala
, but nothing from src/gatling/*
(see below for my setup).
I've experimented with fat jars but that task gives me the error:
Execution failed for task ':fatJar'.
> Cannot expand ZIP 'D:\projects\load-test\build\classes\java\main' as it does not exist.
I have no idea why it expects java in the first place.
The structure of my project is as follows:
load-test/
├── src/
│ ├── gatling/
│ │ ├── resources
│ │ └── scala
│ ├── main/
│ │ ├── resources
│ │ └── scala
│ └── test/
│ ├── resources
│ └── scala
├── ...
└── build.gradle
I've found out, that the Gatling plugin is very stubborn and it only includes the Gatling depencies in gatlingCompileClasspath
. So In order to be able to write a loadtest, I need to have a gatling
sourceset. The main/scala
dir is used to implement some utility functions such as creating custom timestamps etc. test/scala
tests those.
My build.gradle
is as follows:
plugins {
id "com.github.maiflai.scalatest" version "0.25"
id 'io.gatling.gradle' version "3.4.0"
id "scala"
}
apply plugin: "scala"
apply plugin: "com.github.maiflai.scalatest"
compileScala.targetCompatibility = 1.8
ScalaCompileOptions.metaClass.useAnt = false
repositories {
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
}
sourceSets {
gatling {
scala.srcDirs = ["src/gatling/scala"]
resources.srcDirs = ["src/gatling/resources"]
}
test {
scala.srcDirs = ["src/test/scala"]
resources.srcDirs = ["src/test/resources"]
}
}
dependencies {
testCompile "gradle.plugin.com.github.maiflai:gradle-scalatest:0.25"
testCompile "org.scala-lang:scala-library:2.12.12"
testCompile 'org.scalatest:scalatest_2.12:3.0.0'
testRuntime 'org.pegdown:pegdown:1.4.2'
}
gatling {
toolVersion = '3.4.0'
scalaVersion = '2.12.12'
simulations = {
include "**/*Simulation.scala"
}
systemProperties = ['file.encoding': 'UTF-8']
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Version': project.version,
'Main-Class': 'io.gatling.app.Gatling'
}
setArchiveBaseName project.name + '-all'
from {
configurations.gatlingRuntimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
}
with jar
}
After a lot of experimenting and hours of searching for hints in the documentation, this is the build gradle snippit that did the trick:
configurations {
fatJarDependencies.extendsFrom gatling
}
task fatJar(type: Jar, dependsOn: [':gatlingClasses', ':processResources']) {
manifest {
attributes 'Implementation-Title': 'Preparing test',
'Implementation-Version': '',
'Main-Class': 'io.gatling.app.Gatling'
}
classifier = 'all'
from files(sourceSets.main.output.classesDirs)
from files(sourceSets.gatling.output)
from { configurations.fatJarDependencies.collect { it.isDirectory() ? it : zipTree(it) } } {
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
}
with jar
}
The key are the following:
1. configurations
fatJarDependencies.extendsFrom gatling
You need to extend gatling
, because something like configurations.gatlingRuntimeClasspath.collect
or configurations.gatling.collect
does nothing in your fatJar task, even though those configurations exists (the latter at least). This is necessary in order to get the dependencies into your jar (gatling itself, scala and whatnot).
2. dependsOn
To be precise:
(type: Jar, dependsOn: [':gatlingClasses', ':processResources'])
Especially gatlingClasses
, which I found through scanning the documentation page of the gatling gradle plugin. This adds the code under src/gatling/*
I can run a simulation by executing the following (-DConfig
is optional):
java -Dconfig.resource=myConf.conf -jar the-jar-i-created.jar -s org.comp.pckg.DemoSimulation
As pointed out by George Leung, it is also possible to generate the reports outside of the jar, if you start the comment as above (I mistakenly forgot that I added the option -nr
). In order to customize the folder I added a gatling.conf
in src/gatling/resources
with the following values:
gatling {
core {
directory {
results = "/gatling/reports"
}
}
}
This overrides the default values that you can find here.