Coder Social home page Coder Social logo

gatling-tutorial-sbt's People

Contributors

enriquezrene avatar

Watchers

 avatar  avatar

gatling-tutorial-sbt's Issues

duplicated code

When I'm writing a new simulation I'm currently duplicating code, particularly this snippet:

val httpProtocol = http
    .baseURL("https://api.github.com")
    .userAgentHeader("enriquezrene")
    .acceptHeader("application/vnd.github.v3+json")

Done When:

  • A way to avoid duplicate the above code snippet is implemented and well documented

Delete .idea folder

Delete .idea folder from project

Done When

  • Folder does not exist anymore
  • An entry is added on .gitignore file

travis

Include travis as part of the project

loop

Implement looping with https://api.github.com/user/repos?page=2&per_page=1
Take a look on:

Advanced Tutorial

In this section, we assume that you have already gone through the Quickstart section and that you have a basic simulation to work with. We will apply a series of refactorings to introduce more advanced concepts and DSL constructs.

Step 01: Isolate processes
Presently our Simulation is one big monolithic scenario.

So first let us split it into composable business processes, akin to the PageObject pattern with Selenium. This way, you’ll be able to easily reuse some parts and build complex behaviors without sacrificing maintenance.

In our scenario we have three separated processes:
Search: search models by name
Browse: browse the list of models
Edit: edit a given model
We are going to extract those chains and store them into objects. Objects are native Scala singletons. You can create those in dedicated files, or directly in the same file as the Simulation.

object Search {

val search = exec(http("Home") // let's give proper names, as they are displayed in the reports
.get("/"))
.pause(7)
.exec(http("Search")
.get("/computers?f=macbook"))
.pause(2)
.exec(http("Select")
.get("/computers/6"))
.pause(3)
}

object Browse {

val browse = ???
}

object Edit {

val edit = ???
}
We can now rewrite our scenario using these reusable business processes:

val scn = scenario("Scenario Name").exec(Search.search, Browse.browse, Edit.edit)
Step 02: Configure virtual users
So, this is great, we can load test our server with... one user! Let’s increase the number of users.

Let’s define two populations of users:
regular users: they can search and browse computer models.
admin users: they can search, browse and also edit computer models.
Translating into a scenario this gives:

val users = scenario("Users").exec(Search.search, Browse.browse)
val admins = scenario("Admins").exec(Search.search, Browse.browse, Edit.edit)
To increase the number of simulated users, all you have to do is to change the configuration of the simulation as follows:

setUp(users.inject(atOnceUsers(10)).protocols(httpConf))
Here we set only 10 users, because we don’t want to flood our test web application. Please, be kind and don’t crash our server ;-)

If you want to simulate 3000 users, you might not want them to start at the same time. Indeed, real users are more likely to connect to your web application gradually.

Gatling provides rampUsers to implement this behavior. The value of the ramp indicates the duration over which the users will be linearly started.

In our scenario let’s have 10 regular users and 2 admins, and ramp them over 10 seconds so we don’t hammer the server:

setUp(
users.inject(rampUsers(10) over (10 seconds)),
admins.inject(rampUsers(2) over (10 seconds))
).protocols(httpConf)
Step 03: Use dynamic data with Feeders and Checks
We have set our simulation to run a bunch of users, but they all search for the same model. Wouldn’t it be nice if every user could search a different model name?

We need dynamic data so that all users don’t play exactly the same scenario and we end up with a behavior completely different from the live system (due to caching, JIT etc.). This is where Feeders will be useful.

Feeders are data sources containing all the values you want to use in your scenarios. There are several types of Feeders, the most simple being the CSV Feeder: this is the one we will use in our test.

First let’s create a file named search.csv and place it in the user-files/data folder.

This file contains the following lines:

searchCriterion,searchComputerName
Macbook,MacBook Pro
eee,ASUS Eee PC 1005PE
Let’s then declare a feeder and use it to feed our users with the above data:

object Search {

val feeder = csv("search.csv").random // 1, 2

val search = exec(http("Home")
.get("/"))
.pause(1)
.feed(feeder) // 3
.exec(http("Search")
.get("/computers?f=${searchCriterion}") // 4
.check(css("a:contains('${searchComputerName}')", "href").saveAs("computerURL"))) // 5
.pause(1)
.exec(http("Select")
.get("${computerURL}")) // 6
.pause(1)
}
Explanations:
First we create a feeder from a csv file with the following columns: searchCriterion, searchComputerName.
As the default feeder strategy is queue, we will use the random strategy for this test to avoid feeder starvation.
Every time a user reaches the feed step, it picks a random record from the feeder. This user has two new session attributes named searchCriterion, searchComputerName.
We use session data through Gatling’s EL to parametrize the search.
We use a CSS selector with an EL to capture a part of the HTML response, here a hyperlink, and save it in the user session with the name computerURL.
We use the previously saved hyperlink to get a specific page.
Note

For more details regarding Feeders, please check out Feeder reference page.

For more details regarding HTTP Checks, please check out Checks reference page.

Step 04: Looping
In the browse process we have a lot of repetition when iterating through the pages. We have four times the same request with a different query param value. Can we change this to not violate the DRY principle?

First we will extract the repeated exec block to a function. Indeed, Simulation‘s are plain Scala classes so we can use all the power of the language if needed:

object Browse {

def gotoPage(page: Int) = exec(http("Page " + page)
.get("/computers?p=" + page))
.pause(1)

val browse = exec(gotoPage(0), gotoPage(1), gotoPage(2), gotoPage(3), gotoPage(4))
}
We can now call this function and pass the desired page number. But we still have repetition, it’s time to introduce another builtin structure:

object Browse {

val browse = repeat(5, "n") { // 1
exec(http("Page ${n}")
.get("/computers?p=${n}")) // 2
.pause(1)
}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.