Hi,
I am using Gatling to load test à Vaadin project which use a lot a polling mechanism. I have to perform a lot of requests which are optional, depending the state of the server.
Here is some proposal of features. I can submit pulling request, but the way it’s implemented is probably not the better. It could be better located in the DSL.
HttpConditionalCheck
I developped an HttpConditionalCheck which is a wrapper for a nested HttpCheck. The nested check is performed only if the (Session, Response) => Boolean apply to be true.
I use it like this : http.check(doCheckIf(session, response => true)(substring(“foo”)))
This check is very usefull to me, because it allow me to perform a check if another check is a success (some attributes extracted by another previous check is in session).
It allow me to go farest for exemple, by performing one check on every request while polling is in progress, and throw validation failure only if the check was a failure on every responses.
For now, here is my implementation :
/** Perform a conditional check. */
def doCheckIf(condition: (Session, Response) => Validation[Boolean])(nestedCheck: HttpCheck) = new HttpConditionalCheckBuilder(condition, nestedCheck)
val dummyPreparer: Preparer[Response, Response] = HttpCheckBuilders.PassThroughResponsePreparer
val dummyExtractor: Expression[Extractor[Response, Response]] = new HttpDummyExtractor().expression
class HttpDummyExtractor extends Extractor[Response, Response] {
def name = “dummy”
def arity = “dummy”
def apply(prepared: Response): Validation[Option[Response]] = { Success(Option(prepared)) }
}
/** Perform nestedCheck if condition is true. */
class HttpConditionalCheck(wrapped: Check[Response], condition: (Session, Response) => Validation[Boolean], nestedCheck: HttpCheck)
extends HttpCheck(wrapped, HttpCheckScope.Body, None) {
val checkUuid: String = UUID.randomUUID.toString
def performNestedCheck(response: Response, session: Session)(implicit cache: mutable.Map[Any, Any]): Validation[CheckResult] = {
logger.trace(“Check: [{}] condition is true: perform nested checks.”, checkUuid)
nestedCheck.check(response, session)
}
override def check(response: Response, session: Session)(implicit cache: mutable.Map[Any, Any]): Validation[CheckResult] = {
val validationResult = condition.apply(session, response).flatMap { c => {
if (c) {
performNestedCheck(response, session)
} else {
logger.trace(“Check: [{}] condition is false: do not perform nested checks.”, checkUuid)
//wrapped.check(response, session)
CheckResult.NoopCheckResultSuccess
}}
}
validationResult
}
}
I am sure it’s not the best we can do, but I not dived deeper enough in the architecture yet to see all impacts.
Scenario session attibutes
I am struggling with the attributes extracted in session. When a user perform a logout, I want to reset the Session, but it reset loops to. I think it would be great to have a feature which remove every “scenario attributes” extracted or added during the scenario, but not technical ones like attributes used for looping. I didn’t go further implementing this behaviour yet.
ConstantPauseBuilder
I need to use in my scenarios an irreductible / invariant / constant pause between polling request, even if the setup change the pauses behaviour. Here is my implementation, it could be usefull in the DSL too.
/** PollingPauseBuilder ignore force parameter and use a constant generator. */
class ConstantPauseBuilder(duration: Expression[Duration], force: Option[PauseType]) extends ActionBuilder {
def build(system: ActorSystem, next: ActorRef, ctx: ScenarioContext) = {
val generator = Constant.generator(duration)
system.actorOf(Pause.props(generator, ctx.statsEngine, next), actorName(“pause”))
}
}
Modifying Request before sending them
I use the recorder to record my scenarios. I need to modify a lot the requests stored in files used with RawFileBody(). For example, I have to modify evry request file to add my dynamic CSRF token in it. Firstly, I think it would be great to have the possibility to use StringBody instead of RawFileBody with the recorder. Secondly, I implemented a way to parse all my requests to apply some modifications on it like it is available on response with transformResponse. With this, I can replace all static texts recorded by dynamic EL before building the scenario.
What to you think about this proposals ?