Affichage des articles dont le libellé est gatling. Afficher tous les articles
Affichage des articles dont le libellé est gatling. Afficher tous les articles

dimanche 29 septembre 2013

Gatling dynamic parameters example

It is very easy to create a stress test with Gatling when you know the parameters to send within each HTTP request. But sometimes you have to handle dynamic parameters and this is more complicated to manage.

A typical case where dynamic parameters are needed is when you are testing a page with a form protected with a CSRF protection, for example :

<form action="/deleteAccount" method="POST">
  <input type="hidden" name="login" value="jsebfranck"/>
  <input type="hidden" name="verificationToken" value="wQvhCLsPHVbKd9ANoOZTpBsXtVhpG0h3"/>
</form>

For each display of this form, the verificationToken parameter expected on the server side will be different. This protection against CSRF attacks allows to be sure that the POST request is send from a form generated by the website, and not from another website.

If you use the gatling recorder to display the form page then submit the form, it will generate the following test :

val scn = scenario("delete account")
      .exec(http("get delete account page")
        .get("/Account/Delete")
        .headers(headers_1))
      .exec(http("delete account")
        .post("/Account/Delete")
        .headers(headers_5)
        .param("verificationToken", "wQvhCLsPHVbKd9ANoOZTpBsXtVhpG0h3")
        .param("login", "jsebfranck"))

The problem with this test is that it always sends the same verificationToken parameter within the form. So if you launch it, it will failed because the verificationToken will be different from the expected verificationToken.

To resolve this problem you have to parse the page with the form in order to retrieve the verificationToken parameter and to send it within the form. To do that you can use two advanced features of gatling, the "session" and the "saving data" features :

val scn = scenario("delete account")
      .exec(http("get delete account page")
        .get("/Account/Delete")
        .headers(headers_1)
        .check(
          regex("""<input name="verificationToken" type="hidden" value="([^"]*)" />""")
          .saveAs("requestVerificationToken")))
      .exec(http("delete account")
        .post("/Account/Delete")
        .headers(headers_5)
        .param("verificationToken", "${requestVerificationToken}")
        .param("login", "jsebfranck"))

The check method allows to do operations on the result of the request. Here we apply a regex to get the content of the value attribute, then we save it in the requestVerificationToken variable with the saveAs method :

    .check(
      regex("""<input name="verificationToken" type="hidden" value="([^"]*)" />""")
      .saveAs("requestVerificationToken")))

Then we can reuse the requestVerificationToken variable to send it within the form :

    .param("verificationToken", "${requestVerificationToken}")

Now you are able to use dynamic parameters in a Gatling test. I hope this example will help you to bypass most of the constraints of a website. For further information on gatling advanced usages, please visit this page.

jeudi 29 août 2013

Easy stress tests with Gatling

A few month ago, I needed to compare the response time of several webapp pages before and after upgrading a cache component. I thought the easier and faster way to do that would be to write a shell script doing several http calls to the webapp using wget, and to compute myself the average response time. I did that, it worked and I had my expected conclusion that the new cache version was faster. Of course, I wrote my shell script in a dirty way and it finally finished to the trash.

Then I hear about Gatling, a simple alternative to JMeter to do stress tests. I tested it and indeed it was very easy to use it, and even faster than creating an homemade script.

Today I would like to show you how it is easy to write a stress test with this tool.


Start easily with the recorder



Gatling provides an HTTP recorder tool allowing to generate a Gatling test. It is a good way to generate a first test.

To do that :

1. Download a Gatling archive and extract it
2. Launch the recorder : ./bin/recorder.bat or ./bin/recorder.sh
3. Configure where the test must be generated, for that you can change the fields "package", "class name", and "ouput folder" :

Gatling recorder configuration

4. Configure your web browser to use Gatling as a proxy. As see in the recorder configuration, the http port is 8000 and the https port is 8001.

Web browser configuration
5. Press the start button in the recorder
6. Go to the pages you want to test in the web browser
7. Press the stop & save button in the recorder
8. Open the generated test. In this example the test has been generated under C:\gatling-stress-tests\com\mycompany\stresstests\MyFirstStressTest.scala
9. Delete the useless requests. For example in my stress test I don't want the requests retrieving the static resources or the google analytics requests.
10. Rename the scenario and the http methods giving comprehensive titles : we will find these titles in the test reports.
11. Change the count of users to do 50 simultaneous connections to the webapp

Congratulations you have created your first Gatling test :

import io.gatling.core.Predef._
import io.gatling.core.session.Expression
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import io.gatling.http.Headers.Names._
import io.gatling.http.Headers.Values._
import scala.concurrent.duration._
import bootstrap._
import assertions._

class MyFirstStressTest extends Simulation {
  val httpProtocol = http.baseURL("http://mywebsite.com")
                         .acceptHeader("image/png,image/*;q=0.8,*/*;q=0.5")
                         .acceptEncodingHeader("gzip, deflate")
                         .acceptLanguageHeader("fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3")
                         .connection("keep-alive")
                         .userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0")
  val headers_1 = Map("""Accept""" -> """text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8""")
  val headers_5 = Map("""Accept""" -> """text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8""",
                      """Content-Type""" -> """application/x-www-form-urlencoded""")
  
  val scn = scenario("my first test")
     .exec(http("home page").get("""/""").headers(headers_1))
     .exec(http("login page").get("""/Account/Login""").headers(headers_1))
     .exec(http("login").post("""/Account/Login""").headers(headers_5)
                        .param("""UserName""", """jsebfranck""")
                        .param("""Password""", """my password""")
     .exec(http("news").get("""/News""").headers(headers_1))

  setUp(scn.inject(atOnce(50 user))).protocols(httpProtocol)
}

As you can see, a Gatling test is a Scala script. Don't worry if you don't know Scala, this script is easy to understand, you don't have to understand all Scala mechanisms :
  • httpProtocol variable defines the global parameters to connect to the website
  • headers_1 and headers_5 defines http headers parameters 
  • scn is the test scenario with the title "my first test"
  • the test contains 4 http calls (3 GET and 1 POST) called "home page", "login page", "login" and "news"
  • setUp allows to launch the test
  • atOnce(50 user) indicates that 50 connections will be done simultaneously

Launch the test

Launch a Gatling test is very easy :

1. Launch the gatling executable : ./bin/gatling.bat or ./bin/gatling.sh
2. Select the MyFirstStressTest test
3. Open the HTML report generated in results folder

Several graphics are generated in the report. But two graphics are particularly interesting. The first one give for each HTTP request :
  • the minimum, maximum and average response time
  • the standard deviation : deviation of the requests response time compared to the average response time. A small standard deviation means that the response time is almost the same for each request
  • the 95 percentile : means that 95% of the requests are under this response time 
  • the 99 percentile : means that 99% of the requests are under this response time



If you click on a request title, for example "news", you get more information specific to the request. Here we can see the response time evolution based on the active sessions.


Conclusion

I hope you understood it is not complicated to use a stress test tool like Gatling, even if it is rare for you to do performance benchmarks. This example is very basic and doesn't show all great features of Gatling. If you want to go further, I encourage you to read the following documentations :