The Art Of Destroying Your Web App With Gatling (to make it more resilient)

The Art Of Destroying Your Web App With Gatling (to make it more resilient)

 

This is the English version of a blog post we wrote in French for D2SI:

http://blog.d2-si.fr/2018/03/05/gatling-test-performance/

 

Warning: Gatling could harm your application, use it with caution!

But don’t worry! This article is a short introduction to Performance Testing with Gatling: You will learn the basics of performance testing and how to start using Gatling. If you ever have experienced performance issues or if moving to production is your worst nightmare, this article is made for you!

What does performance testing mean?

A performance test let you measure the performance and robustness of your application. The aim is to simulate a high number of concurrent users, as close as possible to real cases. You can then anticipate crashes and have a more precise vision of the response times of all your users, especially those with the worst response times.

There are different types of performance tests:

  • Load test: Simulating an expected load of users
  • Capacity test: Increasing step by step the number of users during the simulation, in order to know the limits of your system
  • Stress test: Simulating a very high number of users using your application at the same time
  • Soak test: Simulating users over a long period of time, in order to detect any performance degradations over time

Why testing as soon as possible is important

There are development teams who contact us, at Gatling Corp, because they need performance tests. But in some cases, they contact us just before they move in production, or even after a first crash. In the first case, there won’t be enough time to fix the performance issues we could detect, in the second case, a crash already happened.

It doens’t mean that testing in these cases is useless, quite the contrary: You will identify your app’s bottlenecks. But there is a more efficient way to do performance testing: Starting from the very beginning of the development cycle. There is no need to wait!

The sooner the performance problems are detected, the sooner we can fix those. It saves money and time, and it improves the quality of your application.

Performance tests are also very useful to know beforehand the required infrastructure to move your application in production.

Gatling, by Gatling Corp

Gatling is an open-source load and performance testing tool for web applications. It is developed by Gatling Corp and works on all Operating Systems.

Gatling makes it easy to scripts performance tests, and to maintain them throughout the development of your application. Gatling is a powerful tool, able to generate a very high number of users from a single load injector. Gatling provides you with dynamic, exhaustive and colorful HTML reports.

Let’s test with Gatling!

Gatling’s simulations are Scala files. However a prior knowledge of Scala is not required: Gatling comes up with a simple DSL (Domain Specific Language) to script your simulations.

You can also use Gatling’s recorder to bootstrap your simulations. It will record all your actions on your website and create a ready-to-use Gatling simulation.

Running a Gatling test

Once you are done with the scripting part, you can run it with Gatling’s bundle, or directly from your build tool (Maven, Sbt or Gradle).

To show you how Gatling works, let’s test this website http://computer-database.gatling.io with a Gatling simulation. This website is a basic CRUD application (“Create, Read, Update, Delete”). It is designed to manage a stock of computers.

HTTP Configuration

The first step is to deal with the HTTP configuration. Here you can define the base url of all your requests and the HTTP headers sent with each of these requests:

val httpConf = http
  .baseURL("http://computer-database.gatling.io") // Here is the root for all relative URLs
  .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") // Here are the common headers

Scripting requests

Let’s create our scenario, named “BasicSimulation”:

val scn = scenario("BasicSimulation")

Now, let’s add a simple GET request:

val scn = scenario("BasicSimulation")
  .exec(http("Get Computers").get("/computers"))

These keywords are important:

  • exec means we are performing an action
  • http indicates that we are dealing with a HTTP request named “Get Computers”
  • get means the GET request is on the endpoint “/computers”

Now, let’s see how to add a new computer in our stock:

val scn = scenario("BasicSimulation")
  .exec(http("Get Computers").get("/computers"))
  .exec(http("Add Computer").post("/computers")
    .formParam("name", "Beautiful Computer")
    .formParam("introduced", "2012-05-30")
    .formParam("discontinued", "")
    .formParam("company""", "37"))

This time, we are using the POST method to indicate that we want a POST-type request. We can then define the parameters with the method “formParam” (for instance, the parameter “name” value is “Beautiful Computer”).

In our scenario, Gatling will send a GET request then a POST request. However, it doesn’t match a realistic user’s behavior for the moment. In real life, a user will take time to read and scroll down the page before clicking on a button. Let’s add a pause of 5 seconds between the requests:

val scn = scenario("D2siSimulation")
  .exec(http("Get Computers").get("/computers"))
  .pause(5)
  .exec(http("Add Computer").post("/computers")
    .formParam("name", "Beautiful Computer")
    .formParam("introduced", "2012-05-30")
    .formParam("discontinued", "")
    .formParam("company""", "37"))

Setup

Let’s now combine our HTTP configuration and the requests we just crafted, in order to have a functional Gatling script. We need to add an injection profile: 100 users at once.

setUp(scn.inject(atOnceUsers(100)).protocols(httpConf))

You need to start with the keyword setUp. Then use the keywords inject and atOnceUsers to define how many users you want in your system. And don’t forget to mention the HTTP configuration you are using with the keyword protocols.

With Gatling, it is also possible to shape more complex injection profiles: You can have users arriving at a constant rate, stage by stage or at specific times.

Assertions = acceptance criteria

Gatling is now able to run your scenario with 100 users. But now we want to make sure that every request has a response time lower than 2 seconds: Gatling is able to check that this assumption is valid. It is called an assertion in Gatling’s DSL:

setUp(scn.inject(atOnceUsers(100)).protocols(httpConf))
  .assertions(global.responseTime.max.lt(2000))

Insert the keyword assertions after the setup! In this case, the maximum response time should be lower than 2000 milliseconds, or 2 seconds.

Last step

The last step is to combine together all the pieces we previously crafted. We need to put our script inside a class, which extends the Simulation class:

class D2siSimulation extends Simulation {

  val httpConf = http
    .baseURL("http://computer-database.gatling.io") // Here is the root for all relative URLs
    .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") // Here are the common headers

  val scn = scenario("BasicSimulation")
    .exec(http("Get Computers").get("/computers"))
    .pause(5)
    .exec(http("Add Computer").post("/computers")
      .formParam("name", "Beautiful Computer")
      .formParam("introduced", "2012-05-30")
      .formParam("discontinued", "")
      .formParam("company", "37"))

  setUp(scn.inject(atOnceUsers(100)).protocols(httpConf))
    .assertions(global.responseTime.max.lt(2000))
}

The Test’s Results

In order to have more interesting test results, I slightly changed the configuration of the injection profile, but not the configuration of the requests itself.

You can see the results in real time in the console, when you run the test. You can check the progress of your simulation with a few indicators regarding the requests and the users:

At the end, Gatling will generate a HTML report. It will provide you with way more information, expecially the response times of all your requests.

Or even how the number of users changes during the simulation:

And the response times and their distribution over time:

And the number of requests and responses:

The Test’s Results with Gatling FrontLine

Gatling Corp also edits Gatling FrontLine, Gatling’s Enterprise Version. Gatling FrontLine is a web app to manage easily your Gatling tests. You can also manage clusters of load injectors (to simulate a very high number of users). Gatling FrontLine provides you also with more metrics (TCP connection, bandwidth, DNS resolution, injectors’ monitoring).

You can see below a screenshot of the results of our Gatling simulation:

Now test your own app!

You know what a performance test is and how to create a simulation with Gatling. You can now make sure that your web app won’t crash! No need to cross your fingers next time you move in production!

We will be back shortly for a new article presenting more advanced aspects of Gatling! Stay tuned.

Links

To have more information about Gatling’s features: https://gatling.io/documentation/

If you want to learn more about Gatling FrontLine, Gatling’s Enterprise version, check this out: https://gatling.io/gatling-frontline/

You can find the Gatling simulation we crafted here:
https://github.com/ccedric/GatlingArticles/blob/master/1Basics/src/test/scala/computerdatabase/BasicSimulation.scala

Feel free to contact us: contact@gatling.io!

 

Cedric Cousseran

Cedric is one of Gatling’s and Gatling FrontLine’s developpers.

Posted in Tech
Posted on 7 March 2018