Conditional params, queryParams, headers, etc.

I’m testing a restful service.

There are four ways it can be interacted with:

  1. Regular authenticated user through the Layer7 network layer
  2. Trusted Client through Layer7
  3. Regular, direct to application server
  4. Trusted, direct to server

The difference between those test conditions are in the queryParams and Headers that get sent.

The Layer7 is controlled by config. The whole test execution is either one way, or the other. So I could add conditional execution to return a different http() request with the appropriate headers applied. So far, so good. Perhaps ugly and painful, but doable.

The Trusted vs. Regular depends on characteristics of the user in the feed. Which means I have to decide at run time whether to add a queryParam to the request.

Solution 1:
`
.doIfElse( session => session( SOME_VAR ).as[String] == “someValue” ) {
http( desc )
.get( url )
.queryParam( “foo”, “bar” )

} {
http( desc )
.get( url )

}

`

That smacks of a major violation of the DRY principle, and is not very expressive of the real intent. On top of that, you can’t save that into a val and use it in a resources() call.

For my particular need, I can just do something like this:

`
http( desc )
.get( url + “${QUERY_PARAMS}” )

`

Then at the moment when I know if I need to add the universal query parameters or not, I can just set the value of QUERY_PARAMS to an empty string, or to “?foo=bar” and hope that any subsequent calls to .queryParam() will do the right thing.

If I had my way, it would read something more like this:

http( desc ) .get( url ) .if( session => true ) { queryParam( "foo", "bar" ) } // or .queryParamIf( session => true, "foo", "bar" )

But that’s going to require some serious DSL extensions to get something like that built. And naturally, it needs to support .param, .queryParam, and maybe even .check

I have the feeling that conditionals within http requests would benefit more than just me. So I wanted to throw that out there as something to think about and discuss and plan out.

Thoughts? Opinions?

Looks like something horrible to implement as Gatling API wrappers. Would have to be implemented in Gatling.

But then:

  • we would need more demands and strong arguments from the community to decide to implement this.
  • requests with and without such parameters would have the same name, so you wouldn’t be able to track and tell them appart. I suspect that if you have such conditions, you actually want different clear paths. Then, having an immutable DSL so you have request prototypes and derive from them looks already pretty dry to me.

I don’t want different paths. I want a user flow. I want my scenario to describe the INTENT of the flow, and I want my libraries to translate that into the necessary steps to execute that flow in the context of where and how it is being executed.

For example, different “environments” (instances of the application) have different users available. I pull from a different feed file depending on the environment. Thus, I can run the same scenario, without code change, and use a command-line flag to tell it the endpoint to hit. It adapts its behavior accordingly and does the right thing.

But the Performance Lab instance of the application is behind a network appliance, and requires being accessed one way. The instance on the developer’s laptop is not behind that appliance, and so Gatling must access it in a different way. If I run Gatling against the Perf Lab and say there is a problem, I should be able to tell the developer which scenario to run against their development instance and enable profiling, and it “just works.” That would be the goal, any way.

That said, I agree that it may be something of a pain in the rear to implement DSL to support it. But then, something being a pain has not tended to stop me. I’ve spent the time implementing several pains in the rear in order to make my Gatling scenarios read the way I want them to read. :slight_smile:

So this is more of a philosophical question: What are the pros and cons of having the ability to do conditional (run-time) request building/modification? And if we did decide that it was worth having, what would be the best way to implement it?

Pandora box: first conditional query params, then people (you?) will ask for conditional form params, headers, bodies, bodyparts, checks, etc…
And then, they’ll ask for a way to find out which combination turned bad a some point in their simulation, because they have no way to tell requests appart as they all have the same name.

Actually, have your own DSL for this is quite feasible, if you limit your custom methods to last positions (meaning that once your in your DSL, you can’t come back to HTTP request one). This way, you would be able to turn those conditions into doIf blocks.

That would work. But only if .resources() were extended to allow both http() and exec() chains as parameters. Would that be doable, or would there be horrible side-effects?

Not doable atm.

Hi John,

What I am doing in this case is using the ability to get the .queryParam value from session using EL.
If I want to send that query param I add a value and if not I simply leave the value blank.
I do that with a .exec(session => session.set(“qpKey”, “”)) block that comes before the .exec blocks I use to send an HTTP request.

It works for the cases I need it for.
In those cases the query parameter sent blank is simply ignored, as if it was not sent at all.

I hope this works for you as well.

BTW, if since you posted you have come up with a better solution, please do share.