Gatling is a fabulous framework for load and performance testing against web applications. Tests are written in Scala, and since Scala runs on the JVM, you can still use the Java libraries you know and love. And, if you are already using Maven to manage your project then look no further — the Gatling Maven plugin provides support for those of us wishing to continue using Maven for dependency management. This is especially good news if your tests rely on many libraries and you have no wish to duplicate work that’s already been done in an existing pom.xml
.
Here is a great example of how to get the Gatling Maven plugin working. With it, the command to run a test looks something like this:
mvn gatling:test -Dgatling.simulationClass=MySimulation
The only problem with this is it’s a Maven command. The machine running this needs to have Maven installed.
What if you wanted to run the tests somewhere else? I ran into this when I was trying to get a better understanding of a network latency issue. I wanted something a little more portable that I could put into a Docker container, something like a JAR.
The following guide is based on a Stack Overflow question. I have also uploaded a working sample to Github.
Prerequisites
Make sure you have the gatling-maven-plugin set up. It requires the gatling-charts-highcharts dependency,
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.0.0</version>
</dependency>
and the plugin:
<build>
<plugins>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
Step 1: The scala-maven-plugin
The first step is getting all the Scala stuff into the JAR. I find the scala-maven-plugin from net.alchim31.maven to be very straightforward and easy to integrate. I like it because I don’t have to explicitly declare dependencies like the Scala library and the Zinc compiler, it just does it for me.
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.4.4</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
By default, the scala-maven-plugin
only looks in the src/main/scala
directory. For that reason, I moved all my simulation classes to that directory and updated the gatling-maven-plugin
with the new location. For good measure I also moved my gatling.conf
file to src/main/resources
.
<build>
<plugins>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<configFolder>src/main/resources</configFolder
<simulationsFolder>src/main/scala/gatling</simulationsFolder>
</configuration>
</plugin>
</plugins>
</build>
Step 2: The Uber JAR
The real magic happens when the maven-shade-plugin
builds a shaded JAR with everything in it. This includes all of the libraries used in the tests, Gatling, and the Scala support needed to run it all.
Set the mainClass
property to io.gatling.app.Gatling
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.gatling.app.Gatling</mainClass>
</transformer>
</transformers>
<!-- Exclude manifest signature files. https://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar -->
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
Step 3: Build the JAR!
Good old mvn clean install
is all you need to build the jar. It will show up in the target directory alongside a separate folder of compiled test classes.
At this point, a command like this can be used to run a test:
java -cp JAR_NAME io.gatling.app.Gatling -s MySimulation
Extras
Run Script
A run script can make launching tests a lot easier. Something like this run.sh
can be modified to handle user arguments that correspond to test parameters:
#!/bin/sh
USER_ARGS="-Dmy.test.parameter=$1"
JAR_LOCATION=
find -L . -maxdepth 1 -name "*.jar" -type f -exec printf :{} ';'
java $USER_ARGS -cp $JAR_LOCATION io.gatling.app.Gatling -s MySimulation
Logback configuration
You can also add a logback.xml
file to the project to configure logging.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- <appender name="FILE" class="ch.qos.logback.core.FileAppender"> -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- <file>../gatling.log</file> -->
<append>true</append>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Including run.sh, logback.xml, and additional resources as part of the build
In order to make use of the run.sh
script or the logback.xml
configuration file, you’ll want to include them in the build so they are bundled alongside the JAR. The <resources>
section of the <build>
configuration can be used for exactly this purpose.
<resources>
<resource>
<filtering>true</filtering><directory>${project.basedir}/src/main/resources</directory>
<targetPath>${project.build.directory}</targetPath>
<includes>
<include>run.sh</include>
<include>logback.xml</include>
</includes>
</resource>
</resources>