An introduction to Gatling

An introduction to Gatling

FacebookLinkedIn

Introduction

Have you ever wondered how many concurrent users your application could handle? Since I began writing Scala code I wanted to know how “scalable” it really is. You don’t want to be embarrassed when your awesome product gets some traction and stops working with only a few concurrent users. And when it does stop working you want it to recover. This is where load and stress testing is required. And what better way to do this than with a tool written in Scala? This blog post I will introduce the basic usage of Gatling.
Update 19-04-2013: Updated all examples to Gatling 1.4.7.

What is Gatling

Gatling is a Scala-based, high performance load and stress test tool. At Plot we are using it to test our back end on performance and error handling. It has its own (internal Scala) DSL and is based on the Akka actor system and Async HTTP Client/Netty for asynchronous, non-blocking HTTP operations.

Your first test scenario

Okay, let’s get started. First download the gatling-charts-highcharts bundle from the Gatling website and extract its contents. This introduction is based on version 1.3.5 1.4.7. You can add your own simulations to the folder /user-files/simulations. Create a new folder named searchservice for your simulation and create SearchServiceSimulation.scala. Yes, you define the simulations in Scala. But don’t worry; you do not need to be a Scala expert to use Gatling (but it does help ; ) ). Now on to the simulation.
Suppose you’ve got a webservice which offers an awesome new search functionality. Because you only want to provide your beta service to a limited number of users, you require your users to provide credentials using Basic HTTP Authentication. And you provide your users access to the statistics on their search behaviour. The following piece of Scala code is a Gatling test scenario that tests your webservice.

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .repeat(5) {
        exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "life universe everything")
          .basicAuth("username", "password")
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("username", "password")
    )

  setUp(scn.users(100).ramp(20))
}

That’s how easy it is. The code is mostly self-explanatory. We will be simulating 100 users which will be started in a 20 second time window. This results in starting 5 simulated users per second. Each simulated user will perform 5 searches and will view the statistics. You can run your scenario by opening a console in the bin folder, starting Gatling with gatling.sh or gatling.bat and choosing your scenario.

Checking the output

Gatling automatically adds a check that the response should not contain an error (HTTP status 2XX). But we do not know whether the correct results are being returned. For this Gatling provides a Check API. See it in action on line 16 and 23:

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .repeat(5) {
        exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "life universe everything")
          .basicAuth("username", "password")
          .check(regex("42").exists)
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("username", "password")
      .check(regex("5 times").exists)
    )

  setUp(scn.users(100).ramp(20))
}

Using a feeder

In real life, not all your users will have the same credentials (I hope ; ) ). To mimic actual behaviour Gatling provides a feeder. It can feed values to your scenario from different sources (files, Redis, database) using a specific strategy (queue, circular, random).
Let’s say you want to include a feeder with user credentials in your scenario and you have a list of common search terms that users are using. First define the feeders and use the variables in your scenario:

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  val userCredentials = csv("user_credentials.csv").queue
  val searchTerms = csv("search_terms.csv").random
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .feed(userCredentials)
    .repeat(5) {
        feed(searchTerms)
        .exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "${searchterm}")
          .basicAuth("${username}", "${password}")
          .check(regex("${searchresult}").exists)
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("${username}", "${password}")
      .check(regex("5 times").exists)
    )

  setUp(scn.users(100).ramp(20))
}

user_credentials.csv

username, password
user1, password1
user2, password2
...

search_terms.csv

searchterm, searchresult
life universe everything, 42
recursion, recursion
...

Conclusion

Gatling has proven to be an invaluable tool for verifying our applications behaviour. I encourage every developer to give it a try. Be sure to check out the Gatling Recorder for recording scenarios for websites using your browser. Check the documentation for more information and examples and if you get stuck, ask your question on the Google group.

FacebookLinkedIn

An introduction to Gatling

FacebookLinkedIn

Introduction

Have you ever wondered how many concurrent users your application could handle? Since I began writing Scala code I wanted to know how “scalable” it really is. You don’t want to be embarrassed when your awesome product gets some traction and stops working with only a few concurrent users. And when it does stop working you want it to recover. This is where load and stress testing is required. And what better way to do this than with a tool written in Scala? This blog post I will introduce the basic usage of Gatling.
Update 19-04-2013: Updated all examples to Gatling 1.4.7.

What is Gatling

Gatling is a Scala-based, high performance load and stress test tool. At Plot we are using it to test our back end on performance and error handling. It has its own (internal Scala) DSL and is based on the Akka actor system and Async HTTP Client/Netty for asynchronous, non-blocking HTTP operations.

Your first test scenario

Okay, let’s get started. First download the gatling-charts-highcharts bundle from the Gatling website and extract its contents. This introduction is based on version 1.3.5 1.4.7. You can add your own simulations to the folder /user-files/simulations. Create a new folder named searchservice for your simulation and create SearchServiceSimulation.scala. Yes, you define the simulations in Scala. But don’t worry; you do not need to be a Scala expert to use Gatling (but it does help ; ) ). Now on to the simulation.
Suppose you’ve got a webservice which offers an awesome new search functionality. Because you only want to provide your beta service to a limited number of users, you require your users to provide credentials using Basic HTTP Authentication. And you provide your users access to the statistics on their search behaviour. The following piece of Scala code is a Gatling test scenario that tests your webservice.

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .repeat(5) {
        exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "life universe everything")
          .basicAuth("username", "password")
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("username", "password")
    )

  setUp(scn.users(100).ramp(20))
}

That’s how easy it is. The code is mostly self-explanatory. We will be simulating 100 users which will be started in a 20 second time window. This results in starting 5 simulated users per second. Each simulated user will perform 5 searches and will view the statistics. You can run your scenario by opening a console in the bin folder, starting Gatling with gatling.sh or gatling.bat and choosing your scenario.

Checking the output

Gatling automatically adds a check that the response should not contain an error (HTTP status 2XX). But we do not know whether the correct results are being returned. For this Gatling provides a Check API. See it in action on line 16 and 23:

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .repeat(5) {
        exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "life universe everything")
          .basicAuth("username", "password")
          .check(regex("42").exists)
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("username", "password")
      .check(regex("5 times").exists)
    )

  setUp(scn.users(100).ramp(20))
}

Using a feeder

In real life, not all your users will have the same credentials (I hope ; ) ). To mimic actual behaviour Gatling provides a feeder. It can feed values to your scenario from different sources (files, Redis, database) using a specific strategy (queue, circular, random).
Let’s say you want to include a feeder with user credentials in your scenario and you have a list of common search terms that users are using. First define the feeders and use the variables in your scenario:

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import bootstrap._
 
class SearchServiceSimulation extends Simulation {
 
  val userCredentials = csv("user_credentials.csv").queue
  val searchTerms = csv("search_terms.csv").random
 
  // Define the scenario below
  val scn = scenario("Search and view statistics")
    .feed(userCredentials)
    .repeat(5) {
        feed(searchTerms)
        .exec(
          http("Search")
          .post("http://your-webservice/search")
          .param("q", "${searchterm}")
          .basicAuth("${username}", "${password}")
          .check(regex("${searchresult}").exists)
        ).pause(5)
    }
    .exec(
      http("Statistics")
      .get("http://your-webservice/statistics")
      .basicAuth("${username}", "${password}")
      .check(regex("5 times").exists)
    )

  setUp(scn.users(100).ramp(20))
}

user_credentials.csv

username, password
user1, password1
user2, password2
...

search_terms.csv

searchterm, searchresult
life universe everything, 42
recursion, recursion
...

Conclusion

Gatling has proven to be an invaluable tool for verifying our applications behaviour. I encourage every developer to give it a try. Be sure to check out the Gatling Recorder for recording scenarios for websites using your browser. Check the documentation for more information and examples and if you get stuck, ask your question on the Google group.

FacebookLinkedIn

Comments (0)

    Add a Comment

    sign up
    newsletter