Gatling

Of the three load and performance testing tools that I am going to describe Gatling is the new comer. While LoadRunner has been around since 1994 Gatling was first released in 2011 and since then has had 2 major releases with the most current version being 3.3.1. Gatling supports fewer protocols but can easily be used for testing HTTP, HTTPS, Web sockets and REST Api’s. In this sense it is more limited than LoadRunner yet as more and more applications are either browser based or implement a service that is available over the internet Gatling is certainly the right tool for the times. Gatling is an open source tool which uses Scala as the scripting language for writing tests. Why Scala?

  • Scala can interact with Java
  • It can use Java libraries
  • Cleaner code
  • Smaller code thus easier to have an overview

The only prerequisite for using Gatling is that you have a copy of the Java JDK installed on your machine. The Scala code is compiled into byte code which is then executed on the Java Virtual Machine of your Java installation. This has the pleasant side effect that you can use the native Java libraries to help in your testing scripts.

Installation

Gatling is distributed as a zip file that you can download from their homepage, https://gatling.io. Installing it is just a matter of finding a good location and unpacking the zip file.

Ie.

C:\users\myuser\testingapps\gatling-charts-highcharts-bundle-3.3.1

There is really nothing left to do if the JDK is installed. This directory where Gatling is installed should be stored in the environment variable GATLING_HOME. This is not necessary as this information can be determined by the start scripts but it is cleaner and this value can then be used in batch files or shell scripts. It is worth noting that a OpenJDK is also a JDK and worked just fine with Gatling for all of my tests.

Recorder

Gatling actually has a solution for people who are not familiar with Scala. Bundled with Gatling is a recorder which can be used for capturing an interaction between the user and a web site.. This recording tool is used as a proxy when surfing your web pages which allows it to capture all the URL’s and necessary headers. The actual output of this tool is a Scala script that will reproduce the same set of steps including all pauses made by the user. This recorder start script is started from the same directory as the gatling start script (%GATLING_HOME%\bin)

This may sound like very good news that web tests can be recorded except it is perhaps a bit simplistic. A long time ago it was pretty much determined from a web security standpoint that you cannot simply record a series of steps and then allow them to replay that exact set of steps without negative consequences. This type of action actually has its own name – a replay attack. A replay attack is somehow capturing a series of steps, which may also include the users credentials. Because of the inherent danger of allowing a strict copy and replay of a series of steps most if not all non-trivial web pages will have hidden variables that are set at each step but are unique each time you perform the same series of steps. The values form these variables must be used in subsequent steps and thus prevent you from creating a test script from a recording and using it without any changes.

These unique variables must be retrieved from the web pages and used for each test. So although Gatling recorder will capture all the hard coded unique values you will need to amend the test scripts. You will need go through the recorded script and make amendments to parse out these dynamic values and to use them at the correct locations while following the test steps.

If you are familiar with the website being tested you will find these recorded scripts to be fairly easy to read. Below is a small test along with the recorded test of these same steps. This example what you would see if you followed the Gatling quick start tutorial (https://gatling.io/docs/current/quickstart/)

This test will perform the following operations.

  • Goto computer database gatling.io web site
  • Search for computer ASRock
  • Search for computer Mac
  • click on computer (internal id #19)
  • save computer id #19 with these details

This script almost exactly what is produced by the recorder. I have trimmed out a few unimportant steps and have added a few important changes (use my local proxy) and changed the comment values to be representative of what action they are performing.

 import scala.concurrent.duration._
 import io.gatling.core.Predef._
 import io.gatling.http.Predef._
 import io.gatling.jdbc.Predef._
 
 class RecordedSimulation extends Simulation {
 
 var httpProtocol = http
 .baseUrl("http://computer-database.gatling.io")
 .inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.woff2""", """.*\.(t|o)tf""", """.*\.png""", """.*detectportal\.firefox\.com.*"""), WhiteList())
 .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
 .acceptEncodingHeader("gzip, deflate")
 .acceptLanguageHeader("de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7")
 .userAgentHeader("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36")
 
 httpProtocol = httpProtocol.proxy(Proxy("localhost", 31288).httpsPort(31288))
 
 val headers_4 = Map(
 "Proxy-Connection" -> "keep-alive",
 "Upgrade-Insecure-Requests" -> "1")
 
 val headers_7 = Map(
 "Origin" -> "http://computer-database.gatling.io",
 "Proxy-Connection" -> "keep-alive",
 "Upgrade-Insecure-Requests" -> "1")
 
 val scn = scenario("RecordedSimulation")
 .exec(http("search asrock")
 .get("/computers?f=asrock")
 .headers(headers_4)
 .check(status.is(200))
 )
 .pause(3)
 .exec(http("search mac")
 .get("/computers?f=mac")
 .headers(headers_4)
 .check(status.is(200))
 )
 .pause(2)
 .exec(http("fetch computer")
 .get("/computers/19")
 .headers(headers_4)
 .check(status.is(200))
 )
 .pause(2)
 .exec(http("update computer")
 .post("/computers/19")
 .headers(headers_7)
 .formParam("name", "COSMAC VIP")
 .formParam("introduced", "1977-01-02")
 .formParam("discontinued", "")
 .formParam("company", "3")
 .check(status.is(200))
 )
 setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
 } 

What isn’t in the original recording is a status check that the HTTP call succeeded. I have also added a line that will amend the httpProtocol variable to also include my local proxy server. With just a small amount of imagination you can think about passing in a proxy port and host and if the port is not equal to zero then add the proxy to the httpProtocol as part of your test script.

One thing that might not be immediately obvious is that most of the script is not actually running anything but defining the variable scn. This scenario variable is what will be performed by Gatling. The last line of the scala code actually does the setup which will cause this variable to be used by Gatling to call our series of steps.

setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)

In this test script we are going to use only one user and that user should be created all at one time. This sounds pretty silly for a single user, however, if you are speaking about creating 10 or 100 users you can see that immediately quite a load will be created. It is possible that a system which might be able to support 500 concurrent users doesn’t work very well if all 500 start at once within 2 milliseconds. I will cover increasing the number of users and different ways of generating that load later.

My next post will cover how we actually run this script.

This entry was posted in programming and tagged . Bookmark the permalink.