DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

Cover image for Running Load-Test-as-Code Simulations with Gatling
Kaye Alvarado for Developers @ Asurion

Posted on

Running Load-Test-as-Code Simulations with Gatling

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!

Image description

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:

Image description

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
    }
Enter fullscreen mode Exit fullscreen mode

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 {

}
Enter fullscreen mode Exit fullscreen mode

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>" ) )
                                           )
                                      )     
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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))
      )
Enter fullscreen mode Exit fullscreen mode

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)
    )
Enter fullscreen mode Exit fullscreen mode

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   
================================================================================
Enter fullscreen mode Exit fullscreen mode

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
Image description

Standard Statistics per Request
Image description

Active Users over Time
Image description

Responses per Second over Time
Image description

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/

Top comments (0)

Join us at DEV
Yes, this is technically an โ€œadโ€, but really we just want to ask if you want to join DEV. We have 900k+ developers reading, posting, and enjoying community, and would love to have you. ย  Create an account and continue your coding journey.