Running Load-Test-as-Code Simulations with Gatling
Kaye Alvarado
Posted on November 21, 2022
One of the essential skills in DevOps Engineering is Load Testing. Load testing is a type of performance test checking the upper limits of your system by subjecting it to extreme load conditions.
This type of test goes beyond the traditional functional, regression, and integration testing. It safeguards your infrastructure by simulating actual production traffic in a lower environment (non-production), allowing you to tweak capacity or setup scaling thresholds in preparation for these scenarios.
Why Gatling?
Gatling is load-test-as-code. It is a load testing tool that provides the basic capabilities of simulating load test scenarios and is designed with DevOps and CI/CD in mind. Did I mention it is open-source? You can literally download sample code, add a few tests in the template, and perform load testing from your local machine within 10 minutes!
Gatling uses the scala programming language for its simulation code. It combines object-oriented and functional programming in one concise, high-level language. It is very easy to learn, and has a lot of resources available with sample code.
Gatling produces wonderful reports. Each simulation run creates a graphical report allowing you to analyze results better, drilling-down to scenario level metrics.
If you are testing scenarios of user actions within a browser, and you are not fond of creating tests in scala, you can also use the Gatling Recorder. Just simulate the actions one time, export the HAR (HTTP Archive) file from the browser's developer tools, load it in the recorder, and it will magically create your scala code for you!
Gatling Code Basic Structure
To start your load test journey, download Gatling's open source tool from the gatling website. It will be packaged as a zip file, containing the basic structure shown below:
1. Configuration File
Inside the conf
directory, there should be a json formatted gatling.conf
file. This file contains configurable settings for Gatling and its default values.
From this file, go to the directory section and remove the commented code for simulations, resources, and results.
directory {
simulations = "../user-files/simulations" # If set, directory where simulation classes are located
resources = "../user-files/resources" # If set, directory where resources, such as feeder files and request bodies, are located
#reportsOnly = "" # If set, name of report folder to look for in order to generate its report
#binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
results = "results" # Name of the folder where all reports folder are located
}
This will tell gatling to look for simulation files under the user-files/simulations
directory to compile during run, and put the results in the results
directory once the load test completes.
2. Resources
Resources are a set of values that you feed to your simulation tests. You can set up a scenario and use values in any resource file for load tests where you are simulating different parameter values for a single scenario.
I won't be showing this in detail, just know that it exists and what it's for.
3. Simulations
Simulations contain your load tests. It's commonly coded in scala, but it is now available with Java if you are more familiar with this language.
4. Results
Results points to the directory where the report files will be created after you run the load test. You can view sample reports here.
Create Your First Simulation Code
Going back to the simulation file, let's try creating REST API load tests in scala. First, copy the code below to a .scala
file under your simulations
directory.
package loadtestpackage
import io.gatling.core.scenario.Simulation
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class LoadTestSimulation1 extends Simulation {
}
Next, create a variable to store some value mappings that you will use redundantly across multiple APIs that you're testing. Some common use cases for this part is for authorization headers or api keys.
var credentials = Iterator.continually(
Map(
"authorization" -> ( "Basic <BASE64 user:password>" ),
"apikey" -> ( "<apikey random value here>" ) )
)
)
Then, create an http configuration and store it in a variable. You can also add common headers here such as Accept
and Content-Type
.
val httpConf = http.baseUrl("https://www.domain.com")
.header("Accept", value="application/json")
.header("content-type", value="application/json")
Add a scenario
to your test. Notice here that you are feeding the scenario with the credentials
variable. Then, you can use the mapping value within any part of the scenario. Here, I'm using the authorization header and replacing it with the mapped value in my credentials variable. I also defined 200
and 204
status codes as successful responses of this API.
val scn1 = scenario("GetUsersAPI")
.feed(credentials)
.exec(http("GET Users API")
.get("/user/12345")
.header("requestid","GUIDHERE")
.header("Authorization",StringBody("""${authorization}"""))
.check(status.in(200, 204))
)
Setup the load test. Here, I'm injecting 5 concurrent users constantly throughout a duration of 10 minutes using the protocol in my http configuration variable. Other injection options, both open and closed can also be simulated referencing the full guide here. If you have multiple scenarios defined in the same file, you can run them simultaneously by separating the setup code with comma.
setUp(
scn1.inject((constantConcurrentUsers(5).during(10.minutes)))
.protocols(httpConf)
)
Running Your Simulation Code
To run your simulation code, in your terminal, change directory to your bin
folder. It is important to do this step to be able to view compile errors, if any. Run the gatling.sh
script from this directory.
If you have multiple simulation files in your simulation directory, all of those will be separately packaged during compilation and you will be asked to select which of the simulations you wish to run.
You can add a description (i.e. Load Test Run 1
) to identify the simulation run and distinguish it from other runs. This description will be part of the created report once the simulation run is completed.
During the run, the screen will refresh every few seconds, showing the current load test status until it completes.
$./gatling.sh
GATLING_HOME is set to /Users/karina.alvarado/workspace/gatling-charts/highcharts-bundle-3.8.4
Choose a simulation number:
[0] loadtestpackage.LoadTestSimulation1
[1] loadtestpackage.LoadTestSimulation2
0
Select run description (optional)
Load Test Run 1
Simulation loadtestpackage.LoadTestSimulation1 started...
================================================================================
2022-11-11 01:00:00 5s elapsed
---- Requests ------------------------------------------------------------------
> Global (OK=10 KO=0 )
> GET Users API (OK=10 KO=0 )
---- Errors --------------------------------------------------------------------
---- GetUsersAPI ---------------------------------------------------------------
active: 20 / done: 10
================================================================================
Results
If you have monitoring tools setup in your infrastructure such as Kibana, Splunk, SumoLogic, Prometheus, or other equivalent tools, you can always analyze your results to compare environments and how they differ in terms of performance against a heavy load.
If not, you can also use the report generated from the gatling test itself. A few screenshots on how the Gatling report looks like are shown below:
Show Response Time Ranges of Each Scenario
Standard Statistics per Request
Responses per Second over Time
There's a few more graphs shown in Gatling that may be helpful depending on what you are trying to find out. Based on these results, you'll have some data to confirm whether the infrastructure that you're setting up needs to be tweaked to better prepare for real traffic once it's available in production.
References:
https://gatling.io/docs/gatling/reference/current/stats/reports/
https://gatling.io/docs/gatling/reference/current/http/recorder/
Posted on November 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.