问题
We're using Gatling to load test our application (and it works great). We're attempting to DRY up some of the code by making composable extensions on the Gatling classes (like ScenarioBuilder
/ ChainBuilder
/ etc. found in io.gatling.core.structure).
Here is an example of one of our scenarios:
val scn = scenario("Whatever")
.exec(Authentication.FeederLogin(userCsvFile, password))
.exec(User.ExtractId(User.SignIn()))
.exec(FindPeople(50, "personIds"))
// SPA load
.exec(User.FetchLandingPageFor("${userId}"))
.during(durationSeconds.seconds) {
pace(3.seconds, 8.seconds)
.exec(Person.Search("${personIds.random()}"))
.pause(3.seconds, 10.seconds)
// start the upload
.exec(Upload.create())
}
What we'd like to do is start to make some of that composable so we can re-use them in other scenarios. Something like this:
val scn = scenario("Whatever")
.login()
.during(durationSeconds.seconds) {
pace(3.seconds, 8.seconds)
.uploadFor("${personIds.random()}")
}
// ...
object WhateverScenarios {
implicit class ScenarioBuilderWithWhatevers(b: ScenarioBuilder) {
def login() : ScenarioBuilder = {
b.exec(Authentication.FeederLogin(userCsvFile, password))
.exec(User.ExtractId(User.SignIn()))
.exec(FindPeople(50, "personIds"))
}
def uploadFor(whom : String) : ScenarioBuilder {
b.exec(Person.Search("${personIds.random()}"))
.pause(3.seconds, 10.seconds)
// start the upload
.exec(Upload.create())
}
}
}
Full disclosure; I'm not super familiar with Scala. This works, but the problem is in the uploadFor
in that at that point it's working with a ChainBuilder
vs. a ScenarioBuilder
.
I thought
Oh, simple! Just use generics!
Except I cannot get it to work :( It looks like most of these extend StructureBuilder[T] but I cannot seem to get a generic definition defined where I can use my WhateverScenarios
in any context of a StructureBuilder[T]
.
Thanks in advance for any information that can be provided.
回答1:
So I was able to get past my issue, but I'm not entirely sure why I had to do this. What fixed my issue is the following:
object WhateverScenarios {
implicit class StructureBuilderWithWhatevers[B <: io.gatling.core.structure.StructureBuilder[B]](b: B) {
def login() : B = {
b.exec(Authentication.FeederLogin(userCsvFile, password))
.exec(User.ExtractId(User.SignIn()))
.exec(FindPeople(50, "personIds"))
}
def uploadFor(whom : String) : ScenarioBuilder {
b.exec(Person.Search("${personIds.random()}"))
.pause(3.seconds, 10.seconds)
// start the upload
.exec(Upload.create())
}
}
}
The thing that was throwing me for a loop, was originally I tried to define it like this:
object WhateverScenarios {
implicit class StructureBuilderWithWhatevers[B <: StructureBuilder[B]](b: B) {
// ...
}
But when I did that, it didn't recognize login
or uploadFor
as being part of either ScenarioBuilder
or ChainBuilder
. Not sure why, but I had the specify the fully qualified package name for it to work ¯\_(ツ)_/¯
Edit
Turns out that the fully qualified package name was some weird artifact that I had on my machine. Doing a ./gradlew clean
fixed the issue and I no longer have to use the fully qualified path name.
来源:https://stackoverflow.com/questions/50475447/custom-dsl-by-extending-gatling-how-to-scala