6

I'm trying to use two gatling feeders for producing http post request data :

First file contains some fields. One of them is a counter. With this value I'd like to add to my post body as far as lines from second feeder.

For example :

fileA.csv
---------
fileAId,counter
value,3

fileB.csv
---------
fileBId
stack
overflow

I want to construct this string : "value stack overflow stack".

I created a scenario :

object Actions {
    val search = forever() {
        group("Test") {
            exec(feed(FeederUtils.fileAFeeder))
            .exec(  
                http("Test")                                            
                    .post(uri)                          
                    .body(StringBody("""${fileAId} """ +     FeederUtils.generateItems(${counter}.toInt)))
                )
                .pause(20 seconds)
            }
        }
}   

And an object FeederUtils :

object FeederUtils {
    val fileAFeeder= csv("fileA.csv").circular

    var fileBFeeder = csv("fileB.csv").circular

    def generateItems(itemsNumber: Int) : String = {
        var i = 0;
        var returnedString = "";
        for(i <- 0 to itemsNumber) {
            exec(feed(fileBFeeder))
            returnedString = returnedString + """${fileBId} """
        }

        return returnedString ;
    }
}

I have two problems : function call doesn't compile (not found: value $) and feeder variables doesn't exist in generateItems.

I'm new to Gatling & Scala so I think this is evident but I don't understand how exec and feed functions work.

Thanks !

EDIT : Functionnal code is below :

object FeederUtils {
    val fileAFeeder= csv("fileA.csv").circular

    var fileBVector = csv("fileB.csv").records

    var fileBIterator = 0;

    def generateItems(itemsNumber: Int) : String = {
        var i = 0;
        var returnedString = "";
        for(i <- 0 to itemsNumber) {
            var currentItem = fileBVector(fileBIterator)

            //Circular read
            if (fileBIterator < fileBVector.size) { 
              fileBIterator+=1
            } else {
              fileBIterator=0
            }

            returnedString = returnedString + currentItem("fileBId")
        }

        return returnedString ;
   }
}

object Actions {
    val search = forever() {
        group("Test") {
            exec(feed(FeederUtils.fileAFeeder))
            .exec({session => session.set("generatedString",feederUtils.generateItems(session("counter").as[String].toInt))})
            .exec(  
                http("Test")                                            
                    .post(uri)                          
                    .body(StringBody("""${fileAId} ${generatedString}"""))
                )
                .pause(20 seconds)
            }
        }
} 

The concept below is : feed function stores data into session attributes, which can be readed from gatling EL expressions or manually with Session API. I had to combine both.

Links :

Session API

EL Expressions

Session manipulation with exec

N LAMY
  • 225
  • 1
  • 4
  • 14

1 Answers1

1

You can't use a feeder for your second file. At best, you can pull multiple records at once, but names will be translated (fileBId1, fileBId2...).

Load the second file content with Gatling csv parser, so you'll be able to access the records (records field) and store it into a global val.

Feed from the first file.

Then write an exec(function) where you:

  • fetch the counter from the session
  • generate a random offset (ThreadLocalRandom) if you want something like the random strategy, or an AtomicInteger that you would increment if you want something like the circular strategy.
  • fetch records from the second file (use a modulo on the records vector size to get proper indices)
  • compute your final String

Don't try to use Gatling EL in custom code. See doc.

Stephane Landelle
  • 6,990
  • 2
  • 23
  • 29
  • Thks a lot for your reply :) I added functionnal code into the original post (I really don't understand why we're not allowed to add replies : always editing original post adds too much noise and to my mind does not help thread reading. Moreover I wanted to add code samples which seems to be too long for comments). If I'm right, I can use two feeders but only if file columns names are different ? Is there only a specific scope for using them ? – N LAMY Dec 10 '14 at 09:19
  • Column headers define the attribute names, so if you feed from multiple feeders with the same names, you'll end up overriding the previous values. – Stephane Landelle Dec 10 '14 at 11:09