Here is what I NEED to do:
.feed("users.csv") // includes username, password, groupid
// login...
.duration(x) {
feed( csv("${groupid}.csv").random )
// interact with the application using the data in the second .csv file
}
But of course, the csv() function takes a string, not an EL expression. I need to be able to compose that string at the appropriate moment in the scenario execution.
I am able to build the string, like so:
.exec( session => {
feed( csv( session.getAttribute("groupid") + ".csv" ).random )
session
})
But unfortunately, the following execs don't see the data. It looks like some kind of scoping issue to me. I'm guessing the feed() expression is doing exactly what it is supposed to be doing, but because it is not part of the outer chain, it's not being placed where it belongs. Am I supposed to be calling .feed on some object within the session object in order to attach it to the ongoing chain?
Any guidance on how to accomplish what I have set out to do? Thanks!
Feeders are instanciated at the same time as the Simulation. You can't defer it to the Simulation runtime, unless you hack with the underlying tools.
How many of those "groupid" files do you have?
If you have just a few of them, you can use either doSwitch from Gatling 2 current snapshot, or embedded doIf blocks if you run with Gatling <= 2M3a.
.doSwitch("${groupid}") (
"foo" -> feed(csv("foo.csv").random),
"bar" -> feed(csv("bar.csv").random)
)
This can be generalized:
def groupIdFeed(groupId: String) = groupId -> feed(csv(groupId + ".csv").random)
.doSwitch("${groupid}") (
groupIdFeed("foo"),
groupIdFeed("bar")
)
Thanks to Stephane for the information, on which the final solution was built.
Here is what I did that works for 1.5.5:
object Data {
var groupList : List[Int] = List( ... ) // long list of IDs
def branchByGroup ( path: String ) : ChainBuilder = {
var c = bootstrap
groupList.foreach( x => {
c = c.doIf( "${groupId}", x.toString() ) {
feed( csv( path + "/" + x.toString() + ".csv" ).random )
}
})
return c
}
def searchCriteria () : ChainBuilder = branchByGroup( "search" )
def other() : ChainBuilder = branchByGroup( "other" )
}
Then, inside my scenario, I call it, like so:
def scn = scenario("My Scenario")
.feed( credentialSource )
.exec( Login.steps )
.during( loopTime ) {
Data.searchCriteria()
.exec( Search.steps )
The call to Data.searchCriteria
is injecting the .doIf() calls into the chain. If it was not the first thing in the block, I would have had to wrap it in .exec()
of course.
As a side-note, there was a gotcha that I had to figure out. Notice the part that says c = c.doIf
- the function needs to return the END of the chain, as opposed to the beginning. You can't build a chain by attaching everything to the first link in the chain! Simulating what the DSL does requires this call-and-assign approach.
Hope this helps someone other than just me. :)