exitBlockOnFail or clear session to control a flow

Simplified my scenario to confirm the usage.

I am storing itemId in session to use in further execution. I have added doIf so that further execution happens only if itemId was present.

A user will keep cycle through the scenario until the duration in minutes.

If in first execution itemId was stored in session but in second execution POST call fails to generate itemId. I still get the itemId in session.

My expectation is to have clear session for each cycle of scenario for the same user. I tried session.reset but I get this error java.util.NoSuchElementException: key not found: timestamp.

I can use exitBlockOnFail() and change my POST to fail by adding a check if itemId is not present. Is this the recommended approach?

Is there any option? Am I using this correctly?

val testScenario = scenario("Test scenario").during(durationInMinutes) {
    exec(http("Create")
            .post("/items")
                .body(StringBody(session => write(Item(1, "Item name"))(DefaultFormats))).asJSON
                    .check(status.is(201), header("Location")
                        .transform(extractId(".*/items/(.*)".r, _))
                            .saveAs("itemId")))
    .doIf(_.contains("itemId")) {
        // do something with the itemId
    }
}

setUp(testScenario.inject(atOnceUsers(10)))
        .pauses(constantPauses)
            .protocols(httpProtocol)
                .assertions(global.failedRequests.count.is(0))

I’m not sure how much I can help you, but I’ll start with these questions to hopefully guide you:

What are you actually testing? I can’t tell from your description if the POST failing is a fail case or not.

If it’s acceptable for a POST to fail and fallback on what’s already stored in the session, your current code looks acceptable (assuming “itemId” isn’t overriden with an empty value). That being said, you could have instances where your doIf procedures get executed even though the POST request failed, creating inconsistent results.

If it’s unacceptable for a POST request to fail, then you want to use some sort of “get me out of here” mechanism, like exitBlockOnFail.

I’d start by defining your requirements. What are you trying to test, and why? Based on those requirements, what is a success case and what is a failure case? From there, you can decide what the right mechanisms are for you.

Thanks Andrew for your inputs.

I used a simplified example to discuss the concept but probably it caused more confusion.

Imagine a GET call returns list of ids if exists. If not it returns empty list. In both case GET call is successful.

I store the list of ids in session so that I can choose one randomly to make subsequent call to says delete.

In the first run I gets ids so stored in session.
In the second run the GET returns empty so the session object is not updated.
But since it already exists in the session due to previous run my next code executes.

http("List person")
  .get("/persons}")
  .check(status.is(200), jsonPath("$..id").findAll.optional.saveAs("personIds"))

Thanks
Bhushan

Correct me if I’m wrong, but shouldn’t

`
jsonPath("$…id").findAll.optional.saveAs(“personsIds”)

`

always override the session attribute “personsIds”? If there are no ids to find, it should save it as None rather than Some(Seq[Int])
If that’s the case, then something like

.doIf(_("personsIds").asOption[Seq[Int]].isDefined){ //do stuff }

(sorry if the scala isn’t exactly right, been a little bit since I used Gatling).

Andrew,

Exactly that is what I thought but seems if findAll returns nothing it does not execute saveAs at all.

Not sure if I am doing any mistake.

Will check that by writing a test and confirm.

Thanks
Bhushan

Can you please try to add the following (after .doIf(_.contains(“itemId”)) to the scenario to reset the session for each cycle?

.exec(_.remove(“itemId”))

I am already doing that and that works. But I am looking for a better alternative like every cycle of the user starts with a fresh session.

Is there any?

By looking at https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/session/Session.scala, I suspect such option is not available (unless Stephan says otherwise). Session.reset likely removes system attributes that are needed to run your user instance.

My approach is to keep track of the attributes I add to the Session, and remove those that I no longer need at the end of the scenario.

That is correct it does not work and reset removes some attributes which gatling requires.
Currently removing the attribute on my own.

Gatling should provide an option to start the cycle again with clean session. Unless there is rationale behind not to provide such feature.

Thanks
Bhushan

Gatling should provide an option to start the cycle again with clean session. Unless there is rationale behind not to provide such feature.

Well, you’re probably shooting yourself in the foot with a closed workload model. Then, we could provide an way to reset all attributes but the internal ones used by Gatling structures, such as loop, but the thing is you can override those keys.

It will be optional so whoever needs can use.

Logically during the test we are saying new users so surely session has be separate for the user.

I am not blocked as I have workaround of coding to remove the attribute but this feature provides a clean handling.

Thanks
Bhushan