Shuffling elements in Gatling

Warning: This blogpost has been posted over two years ago. That is a long time in development-world! The story here may not be relevant, complete or secure. Code might not be complete or obsoleted, and even my current vision might have (completely) changed on the subject. So please do read further, but use it with caution.
Posted on 31 Jul 2014
Tagged with: [ gatling ]  [ performance ]  [ scala ]  [ testing

On a project where I worked alongside @basdenooijer, we needed to do a quick performance-test on a server. Since our shared hatred against (too) complex gui’s, Bas found an awesome cli-tool called gatling. Basically, like ApacheBench but smarter, and like jMeter, only less complex. With the help of simple scala scripts (yes, that’s a first), you can easily program your tests which in our case is a bit more complex than just clicking links on a page.

On a few occasions, we needed to iterate a list of elements found on a page, and click our way through them. Quite easy with gatling:

var ourChain =
  exec(http("page") 
  .get("/url/to/fetch")
  .check(regex("""a class="paragraph" href="([^"]*)"""").findAll.saveAs("foundLinks"))
  .pause(1 second, 3 seconds)
  .foreach("foundLinks","foundLink"){ anotherChain }

Simply put, it will GET a specified url, collects all the links which matches our regular expression, saves it as a variable. Then it will wait between 1 and 3 seconds, and for each of the links, it will execute another chain (which does other stuff on that page).

Nice, easy, and up and running in literally minutes.

However, it seemed a bit wrong to have tests where every user follows the exact same path. Even though the app wouldn’t care in terms of caching and such, it still didn’t really felt like a real-life simulation. We wanted that a user randomly clicked on the links, not sequentially.

Even though gatling has a nice DSL, we couldn’t find any decent way of transforming our findAll() collection into something randomized. Finally, we hit a blogpost that was talking about fetching a random element (not quite what we wanted, but closer than everything else we’ve found). The only issue was that it would select only 1 element, not all of them randomly. But despite our scala-skills where less than 60 minutes old, we did some hackering to make it work:

var ourChain =
  exec(http("page") 
  .get("/url/to/fetch")
  .check(regex("""a class="paragraph" href="([^"]*)"""").findAll.translate(shuffle).saveAs("foundLinks"))
  .pause(1 second, 3 seconds)
  .foreach("foundLinks","foundLink"){ anotherChain }

So we basically didn’t add much more than a call to a translate function which calls the shuffle function (i have no idea what the “scala”-word is for “function”) after our findAll() and before saveAs(). This function should shuffle the values before saving them into foundLinks. Obviously, it means that every foreach() would return the same random order, but we’re ok with this (maybe we could have shuffled it before calling foreach(), but I have no idea if that actually works :( )

The only thing missing is the shuffle function, which fortunately is easy enough:

val shuffle = (list: Seq[String]) => {
    util.Random.shuffle(list)
 }

It takes a sequence of strings, and returns the shuffled version. Make sure you place this before wherever you will be using the function.

When creating this function, we got an answer (within minutes!) from Stephane Landelle which pointed us to the same way.

So for all the non-scala users: give gatling a go, it seems to be a very nice tool with decent reports , and despite a bit of scala, it’s really easy to get it up and running.

Update

according to Stephane, it’s even easier: just use

findAll().translate(s => util.Random.shuffle(s)).saveAs()

which saves you some additional typing.