Going stateful with Gatling Session API.

Reading Time: 4 minutes

Hello Everyone, In our previous blog post Gatling feeders and feeder strategies we have discussed what are the different ways to inject the data in our simulation from different data sources. 

Today we will discuss:

  • Real-time use case (Problem Statement) 
  • Solution: Gatling Session and Session API
  • Injecting Data with Gatling session API
  • Extracting data with Gatling session API
  • Some common exceptions

Real-time use case (Problem Statement)

While executing the simulation with n number of concurrent users it’s very important to manage the test data between concurrent users. We need to ensure that concurrent users should not play with the same data set, else the test will end up with testing the application cache instead of a real-time app. To avoid this situation we have to make our scenario steps dynamic, based on virtual user-specific data.

Solution (Gatling Session and Session API)

Gatling session API helps us to make our scenario steps dynamic and also helps us to extract the different response attributes and assert them. Before moving on first let’s understand some terminologies:

  • Gatling Session: Gatling Session is a virtual user’s state. It’s a Map[String, Any]. Gatling built on the Akka actor model which is a message-oriented architecture and Gatling session is a message that is passed along scenario workflow.
  • Gatling Session Attributes: Entries in the Gatling session map are known as session attributes.

Injecting Data with Gatling session API (Setting Attributes)

To demonstrate Gatling session let us assume following POST API:

curl --location --request POST 'https://restful-booker.herokuapp.com/booking' \
--header 'Content-Type: application/json' \
--data-raw '{
  "firstname" : "Jims",
  "lastname" : "Browns",
  "totalprice" : 111,
  "depositpaid" : true,
  "bookingdates" : {
      "checkin" : "2018-01-02",
      "checkout" : "2019-01-02"
  },
  "additionalneeds" : "Breakfast"
}'

That returns the following response:

{
"bookingid": 15,
"booking": {
"firstname": "Jims",
"lastname": "Browns",
"totalprice": 111,
"depositpaid": true,
"bookingdates": {
"checkin": "2018-01-02",
"checkout": "2019-01-02"
},
"additionalneeds": "Breakfast"
}
}

Gatling session API provides different methods to inject the data into our simulations.

  • set(key: String, value: Any): Session: add or replace an attribute
 .exec(setSessionAttribute => {
      setSessionAttribute      .set("totalprice", 112)
        .set("additionalNeeds", "Lunch")
    })
  • setAll(newAttributes: (String, Any)*): Session: bulk add or replace attributes
 .exec(setSessionAttributesBulkAdd => {
        setSessionAttributesBulkAdd.setAll(
          "firstname" -> "Jimsa",
          "lastname" -> "Brownsi",
        )
      })
  • setAll(newAttributes: Iterable[(String, Any)]): Session: same as above but takes an Iterable instead of a varags.
  .exec(setSessionAttributesBulkAdd => {
        setSessionAttributesBulkAdd.setAll(
      "depositpaid" -> true,
        "checkin" -> "2018-01-03",
        "checkout" -> "2019-01-03"
        )
      })
  • reset: reset all attributes but loop counters, timestamps and Gatling internals (baseUrl, caches, etc)
.exec(setSessionAttributesReset => {
      setSessionAttributesReset.reset
    })

Extracting data with Gatling session API (Getting Attributes)

Let’s say a Session instance variable named ‘bookingResponse’ contains an integer attribute “bookingId”.

.exec { bookingResponse =>
    val bookingId = bookingResponse("bookingId")
    println("****************" + bookingId)
    bookingResponse
    }

When we try to extract ‘bookingId’ like above code snippet it doesn’t return the value, but a wrapper. So to extract the values we can use access methods in several ways:

  • returns a Int:
.exec { bookingResponse =>
    val bookingId = bookingResponse("bookingId").as[Int]
    println("****************" + bookingId)
    bookingResponse
    }
  • returns an Option[Int]: which is None if the foo attribute is undefined, which is Some(value) otherwise and value is an Int, or is a string that can be parsed into an Int.
.exec { bookingResponse =>
    val bookingId = bookingResponse("bookingId").asOption[Int]
    println("****************" + bookingId)
    bookingResponse
    }
  • returns a Validation[Int]: Which is Success(value) if the foo attribute is defined and value is an Int or is a String that can be parsed into an Int.which is Failure(errorMessage) otherwise.
.exec { bookingResponse =>
    val bookingId = bookingResponse("bookingId").validate[Int]        
    println("****************" + bookingId)
    bookingResponse
    }

Some common exceptions

As we have seen how to inject and extract the simulation data using Gatling session API, now it’s important to understand the exception to get familiar with the failures.

Majorly we see 4 different exceptions while using the Gatling session API. We can see some other exceptions but in that case, we need to dry run the code to find the other cause of failures.

  • NoSuchElementException: If the defined attribute “bookingId” is not defined.
  • NumberFormatException: if the value is a string and can’t be parsed into an Int.
    for ex: we have extracted the firstname from the response and try to parse as an integer.
  • ClassCastException: if the value is a string and can’t be parsed into a char.
  • IllegalArgumentException: if the value is a string and can’t be parsed into a Boolean.

So this is all about Gatling session and session API, In next post, we will discuss about Gatling check API. Thank you.

Reference:

https://gatling.io/docs/current/session/session_api
https://restful-booker.herokuapp.com/apidoc/index.html

Knoldus-blog-footer-image

Written by 

Gaurav is a Module Lead QA Consultant having experience of more than 4.5 years. He is well familiar with core QA concepts and well versed in designing automation frameworks in a microservice environment. He has good hands-on experience in automation tools like ReadyAPI, SoapUI, postman.io, rest-assured.io, Cypress.io, gatling.io, Selenium (Java & Scala) and others. He actively promotes shifting left in the development cycle and understands the project domain to work closely with the development team. He has a good understanding of different domains like Airline, health Care and Shipping and cruising domain.