Whats the best approach to create user surge and drop over time?

So I have a simulation which consists of three different scenarios and it looks like:

setUp(slowScenario.inject(rampConcurrentUsers(1) to (Config.numberOfSlowUsers) during (Config.rampUpDuration minutes))
normalScenario.inject(rampConcurrentUsers(1) to (Config.numberOfNormalUsers) during (Config.rampUpDuration minutes))
fastScenario.inject(rampConcurrentUsers(1) to (Config.numberOfFastUsers) during (Config.rampUpDuration minutes))
.maxDuration(Config.scenarioDuration minutes)

Given that I am running the test for eight hours, I’d like to create a 20% surge in the amount of users at the end of
each hour which will decline after a set time. For example if I am running 1000 users, after 50 minutes I’d like to gradually/randomly add
another 200 users. when I reach an hour, those 200 users will drop gradually/randomly and I will be back to my 1000 users.

Any examples, approaches, links, etc would be highly appreciated!

If anyone is interested in getting an answer for this question, I’ve also post it on Stack overflow with a bit of an update.


Posted a reply to StackOverflow. Short answer: build one injection profile that strings together all the different steps that make up the full duration of the test. You can do this in a loop using a function that returns a list. See SO for pseudo-code.

Thank you very much, an excellent and elegant solution.

I am probably doing something incorrectly here as I am not getting the expected result.

I tweaked Johns suggestion a bit as inject requires a T parameter followed by multiple parameters.
If I am running the following code I am not getting the expected behavior, I get one ramp up followed by a ramp down as can be seen by the screenshot:

setUp(*scenario.*inject(rampUsers(10) during (1 minute),sInjection(1): _*)
.protocols(httpconf)).maxDuration(3 minutes)

I believe you are doing an expression that doesn’t have side-effects, but are expecting side-effects.

seq ++ xyz

is an expression, it does not modify the element on the left, it returns a new sequence that includes all of the elements. You want:

var seq = …

seq = seq ++ …

Thanks again for your help.

I am still unable to get the desired behavior and I am starting to think that it might be due to some settings elsewhere.

Here is my base scenario creation function:

def createScenario(name: String, feed: FeederBuilder, chains: ChainBuilder*): ScenarioBuilder = { scenario(name).feed(feed).forever() { exec(chains) } }

I than create different scenarios using my base createScenario function:

def createUsageScenario(scenarioName: String): ScenarioBuilder = { val scenario = createScenario(Config.testName + "_" + scenarioType, feeder, exitBlockOnFail { exec(executeAndValidate(RestApi.userLogin)) .exec(executeAndValidate(RestApi.transaction1)) .exec(executeAndValidate(RestApi.transaction2)) .during(30 seconds) { foreach("${parameters}", "parameter") { .exec(executeAndValidate(RestApi.transaction3)) .exec(executeAndValidate(RestApi.transaction4)) } } }) scenario }

I create the scenario and lastly the simulation:


var scenario1 = createUsageScenario(“scenario”)

setUp(scenario1.inject(nothingFor(1 second),sInjection(1): _*
).protocols(httpconf)).maxDuration(4 minutes)

def sInjection( hours : Int ) = {
var seq = Seq[OpenInjectionStep](rampUsers(10) during (30 seconds))
var i = hours
while ( i > 0 ) {
seq = seq ++ Seq(nothingFor(3 minutes))
seq = seq ++ Seq(rampUsers(10) during (30 minute))
i -= 1


What I would expect to happen is a test that runs for four minutes, ramps up 10 users over 30 seconds, do nothing for 3 minutes and then ramp 10 users over 30 seconds.
But this is what I actually get:

Now even if I run the test without any function that generates the injection like:

setUp(scenario1.inject( rampUsers(10) during (30 seconds), nothingFor(3 minutes), rampUsers(10) during (30 minute) ).protocols(httpconf)).maxDuration(2 minutes)

I still get the above behavior. Its as if the ‘nothingFor’ continues to execute the scenario
and is completely ignored by the simulation setup.

If anyone is interested, I’ve resoled the issue using a different approach.
The solution is described here: