Skip to content

An example test using Gatling. This runs simulations using Maven plugin, an executable jar file, a Docker container, or as Kubernetes Job

License

Notifications You must be signed in to change notification settings

jecklgamis/gatling-scala-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gatling-scala-example

Build

This is an example test using Gatling. A minimal HTTP server is used as an example system under test.

This example demonstrates a number of ways of running simulations :

  • Running from an executable jar file - this packages the Gatling runtime and simulations into a single jar file
  • Running using Docker - this uses the executable jar file to execute simulations inside a Docker container
  • Running as Kubernetes Job - this uses the Docker image to run test inside a Kubernetes cluster
  • Running using Maven plugin - this uses the Gatling Maven Plugin and runs directly from repo (note Gatling has plugins for Gradle and SBT that might suit your use case)
  • See gatling-server for running simulations using an API server

This is a Github Template project. You can create a copy of this project from a clean slate. Simply click Use this template button.

Requirements

  • JDK 21

Java and Kotlin DSL

Gatling now supports Java and Kotlin DSLs. Here are some example Maven projects.

Getting Started

Start the example app on port 8080. The test app is a minimal HTTP server written in NodeJS. The server simply logs the request and returns any request body or query params it receives.

Ensure you have NodeJS installed :

cd example-app
node http-server.js 8080

The Test App

http-server.js:

var http = require('http');
var port = 5050;

if (process.argv.length <= 2) {
    console.log("Requires port number");
    process.exit();
}

var host = "0.0.0.0";
var port = process.argv[2];

var server = http.createServer(function (request, response) {
    var body = [];
    var request_log = {
        type: "request",
        method: request.method,
        headers: request.headers,
        host: request.headers.host
    };
    request.on('data', function (chunk) {
        body.push(chunk);
    }).on('end', function () {
        body = Buffer.concat(body).toString();
        var message = {"ok": "true", body: body};
        request_log.body = body;
        console.log(JSON.stringify(request_log));
        response.end(JSON.stringify(message))
    });
    response.setHeader('X-Source', 'http-server.js');

});

server.listen(port, function () {
    console.log("HTTP server listening on http://%s:%d", host, port);
});

The Test Simulation

import gatling.test.example.simulation.PerfTestConfig.{baseUrl, durationMin, maxResponseTimeMs, meanResponseTimeMs}
import io.gatling.core.Predef.{StringBody, constantUsersPerSec, global, scenario, _}
import io.gatling.http.Predef.{http, status, _}
import scala.language.postfixOps

class ExampleSimulation extends Simulation {
  val httpConf = http.baseURL(baseUrl)
  val rootEndPointUsers = scenario("Root end point calls")
    .exec(http("root end point")
      .post("/")
      .header("Content-Type", "application/json")
      .header("Accept-Encoding", "gzip")
      .body(StringBody("{}"))
      .check(status.is(200))
    )
  setUp(rootEndPointUsers.inject(
    constantUsersPerSec(PerfTestConfig.requestPerSecond) during (durationMin minutes))
    .protocols(httpConf))
    .assertions(
      global.responseTime.max.lt(meanResponseTimeMs),
      global.responseTime.mean.lt(maxResponseTimeMs),
      global.successfulRequests.percent.gt(95)
    )
}

The PerfTestConfig.scala contains the configurable values such as target url or duration.

object PerfTestConfig {
  val baseUrl = getAsStringOrElse("baseUrl", "http://localhost:8080")
  val requestPerSecond = getAsDoubleOrElse("requestPerSecond", 10f)
  val durationMin = getAsIntOrElse("durationMin", 1)
  val meanResponseTimeMs = getAsIntOrElse("meanResponseTimeMs", 500)
  val maxResponseTimeMs = getAsIntOrElse("maxResponseTimeMs", 1000)
}

Running Test Using Gatling Maven Plugin

The gatling-test-maven in pom.xml is configured behind a Maven profile perf-test. To run the tests, enable the profile when running mvn test command.

mvn test -Pperf-test

The plugin is configured to run gatling.test.example.simulation.ExampleSimulation by default. Override the property simulationClass to run a different simulation.

mvn test -Pperf-test -DsimulationClass=gatling.test.example.simulation.SomeOtherSimulation

The plugin can be configured to run all the simulations by setting the configuration property runMultipleSimulations to true.

Running Test Using Executable Jar

This is a self contained executable jar file containing the Gatling runtime and the simulations.

java -cp target/gatling-scala-example.jar io.gatling.app.Gatling -s gatling.test.example.simulation.ExampleSimulation

Running Test Using Docker Container

Create a Docker container:

mvn clean package 
docker build -t gatling-scala-example .

You alternatively run make dist image.

Run the Docker container:

docker run -e "JAVA_OPTS=-DbaseUrl=http://localhost:8080" \
     -e SIMULATION_NAME=gatling.test.example.simulation.ExampleGetSimulation gatling-scala-example:latest

This runs ExampleGetSimulation test against an HTTP server localhost running on port 8080.

Running Test as Kubernetes Job

This assumes you have a basic knowledge on Kubernetes and a have access to a Kubernetes cluster. This usually means you have a properly configured kubectl config (~/.kube/config). Also ensure you have Python 3 installed.

In this example setup, a Jinja2 template job-template.yaml is used generate the actual Job yaml file to be used in kubectl. The helper script ./create-job-yaml.py is used to generate this file.

The Test Results

This is an example test run result from the IDE.

Simulation gatling.test.example.simulation.ExampleSimulation completed in 59 seconds
Parsing log file(s)...
Parsing log file(s) done
Generating reports...

================================================================================
---- Global Information --------------------------------------------------------
> request count                                        600 (OK=600    KO=0     )
> min response time                                      1 (OK=1      KO=-     )
> max response time                                     10 (OK=10     KO=-     )
> mean response time                                     2 (OK=2      KO=-     )
> std deviation                                          1 (OK=1      KO=-     )
> response time 50th percentile                          2 (OK=2      KO=-     )
> response time 75th percentile                          2 (OK=2      KO=-     )
> response time 95th percentile                          4 (OK=4      KO=-     )
> response time 99th percentile                          5 (OK=5      KO=-     )
> mean requests/sec                                     10 (OK=10     KO=-     )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms                                           600 (100%)
> 800 ms < t < 1200 ms                                   0 (  0%)
> t > 1200 ms                                            0 (  0%)
> failed                                                 0 (  0%)
================================================================================

Reports generated in 0s.
Please open the following <some-dir>/target/results/examplesimulation-1503897964328/index.html
Global: max of response time is less than 500.0 : true
Global: mean of response time is less than 1000.0 : true
Global: percentage of successful requests is greater than 95.0 : true

A more detailed test result in HTML can be found in target/results.

Install Python 3 dependencies

pip3 install jinja2 argparse

Here is a demo run using the helper scripts in deployment/k8s/job.

Kubernetes Job Demo

You should be able to replicate it in your local environment.

cd deployment/k8s/job
./demo-run-in-k8s.sh

For a step by step procedure, read on.

  1. Generate job.yaml from job-template.yaml
cd deployment/k8s/job
./create-job-yaml.py --out job.yaml --name gatling-scala-example --java_opts "-DbaseUrl=http://localhost:8080 -DdurationMin=0.25 -DrequestPerSecond=10" --simulation "gatling.test.example.simulation.ExampleGetSimulation"

job-template.yaml template file.

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ name }}"
spec:
  backoffLimit: 0
  template:
    spec:
      containers:
        - name: gatling-scala-example
          image: jecklgamis/gatling-scala-example
          imagePullPolicy: Always
          env:
            - name: JAVA_OPTS
              value: "{{ java_opts }}"
            - name: SIMULATION_NAME
              value: "{{ simulation_name }}"
      restartPolicy: Never
  1. Create Job
kubectl apply -f job.yaml

Example output:

job.batch/gatling-scala-example created
  1. View Job
kubectl get jobs/gatling-scala-example -o wide

Example output:

NAME                   COMPLETIONS   DURATION   AGE   CONTAINERS             IMAGES                            SELECTOR
gatling-scala-example   1/1           24s        25s   gatling-scala-example   jecklgamis/gatling-scala-example   controller-uid=2f37ee78-09b9-4aa9-90ac-872db13522b6
  1. View Pods
kubectl get pods -l job-name=gatling-scala-example -o wide

Example output:

NAME                         READY   STATUS      RESTARTS   AGE   IP             NODE      NOMINATED NODE   READINESS GATES
gatling-scala-example-2mz4s   0/1     Completed   0          56s   10.244.0.237   okinawa   <none>           <none>
  1. Get Pod Logs
kubectl logs <pod-name>
  1. Delete Job
kubectl delete -f job.yaml

Reference Helper Scripts

The scripts below can be found in deployment/k8s/job directory.

Example Target Apps

Some example apps.

Dropwizard Apps:

Spring Boot Apps:

Flask App:

Links

About

An example test using Gatling. This runs simulations using Maven plugin, an executable jar file, a Docker container, or as Kubernetes Job

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published