Gatling - how to achieve feeders to pick a new value in loop - scala

In Gatling, I am using feeders to pass the values of the coordinates in a request, below is the code. I want on each repeat a new value from the feeder to be picked up. I am get the following error --
/mapping/v2/: Failed to build request: No attribute named 'map 30 (100.0%) x' is defined
Could someone please advice how this can be achieved. thanks.
val mapfeeder = csv(fileName = "data/cordinates.csv").circular
object PDP {
val pdp = group("ABC_01_DetailsPage") {
exec(http("PropertyDetailsPage")
.get("/abc/property/detail.html?propertyId=12345&index=0&q=${address_json6}&qt=address&_qt=address&offset=1&sort=address&limit=20&view=property&mode=&radius=1.0Km&landuse=All")
.check(substring("Change in Median Price")))
}
.pause(duration = 1)
.feed(mapfeeder) //this works but only take the fist value and repeats it 30 times
.group("ABC_02_DetailsPage_MAP") {
repeat(30) {
feed(mapfeeder) // this one fails with the error mentioned in the post
exec(http("/mapping")
.get(uri22 + "?mapTypeId=1006&x=${mapx}&y=${mapy}&z=19&access_token=${maptoken}"))
}
val scn = scenario("RecordedSimulation")
.feed(SearchFeeder)
.exec(Homepage.homepage, Login.login, SearchLink.search, SearchEntry.searchentry, PDP.pdp, Logout.logout)
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)

You're missing a dot to attach your feed and the following exec, so only the result of the last instruction (the exec) is passed to the repeat method.
It should be:
repeat(30) {
feed(mapfeeder)
.exec(
http("/mapping") // <== HERE, DOT WAS MISSING
.get(uri22 + "?mapTypeId=1006&x=${mapx}&y=${mapy}&z=19&access_token=${maptoken}")
)
}

Related

Killing the spark.sql

I am new to scala and spark both .
I have a code in scala which executes quieres in while loop one after the other.
What we need to do is if a particular query takes more than a certain time , for example # 10 mins we should be able to stop the query execution for that particular query and move on to the next one
for example
do {
var f = Future(
spark.sql("some query"))
)
f onSucess {
case suc - > println("Query ran in 10mins")
}
f failure {
case fail -> println("query took more than 10mins")
}
}while(some condition)
var result = Await.ready(f,Duration(10,TimeUnit.MINUTES))
I understand that when we call spark.sql the control is sent to spark which i need to kill/stop when the duration is over so that i can get back the resources
I have tried multiple things but I am not sure how to solve this.
Any help would be welcomed as i am stuck with this.

need help in understanding if the way I am testing a function is correct

I have written this function which is called when a user clicks a link. The function basically creates a copy of the user data with one field altered (thus keeping the original value unchanged i.e. not-mutable) and then updates the database with the new value
def confirmSignupforUser(user:User):Future[Option[User]] = {
println("confirming user: "+user)
val newInternalProfile = user.profile.internalProfileDetails.get.copy(confirmed=true)//new data which should be added in the database
println("old internal profile: "+user.profile.internalProfileDetails.get)
println("new internal profile: "+newInternalProfile)
val newProfile = UserProfile(Some(newInternalProfile),user.profile.externalProfileDetails)
println("old profile: "+user.profile)
println("new profile: "+newProfile)
val confirmedUser = user.copy(profile=newProfile)
for(userOption <- userRepo.update(confirmedUser)) yield { //database operation
println("returning modified user:"+userOption)
userOption
}
}
To test the code, I have written the following spec
"confirmSignupforUser" should {
"change confirmed status to True" in {
val testEnv = new TestEnv(components.configuration)
val externalProfile = testEnv.externalUserProfile
val internalUnconfirmedProfile = InternalUserProfile(testEnv.loginInfo,1,false,None)
val internalConfirmedProfile = internalUnconfirmedProfile.copy(confirmed=true)
val unconfirmedProfile = UserProfile(Some(internalUnconfirmedProfile),externalProfile)
val confirmedProfile = UserProfile(Some(internalConfirmedProfile),externalProfile)
val origUser = User(testEnv.mockHelperMethods.getUniqueID(),unconfirmedProfile)
val confirmedUser = origUser.copy(profile = confirmedProfile)
//the argument passed to update is part of test. The function confirmSignupforUser should pass a confirmed profile
when(testEnv.mockUserRepository.update(confirmedUser)).thenReturn(Future{Some(confirmedUser)})
//// await is from play.api.test.FutureAwaits
val updatedUserOption:Option[User] = await[Option[User]](testEnv.controller.confirmSignupforUser(origUser))
println(s"received updated user option ${updatedUserOption}")
updatedUserOption mustBe Some(confirmedUser)
}
}
I am not confident if I am testing the method correctly. The only way I can check that the confirmed field got changed is by looking at the return value of confirmSignupforUser. But I am actually mocking the value and I have already set the field confirmed to true in the mocked value (when(testEnv.mockUserRepository.update(confirmedUser)).thenReturn(Future{Some(confirmedUser)}).
I know the code works because in the above mock, the update method expects confirmedUser or in other words, a user with confirmed field set to true. So if my code wasn't working, update would have been called with user whose confirmed field was false and mockito would have failed.
Is this the right way to test the method or is there a better way?
You don't need to intialize internalConfirmedProfile in your test. The whole point is to start with confirmed=false, run the confirmSignupforUser method, and make sure that the output is confirmed=true.
You should check 2 things:
check that the return value has confirmed=true (which you do)
check that the repository has that user saved with confirmed=true (which you don't check). To check that you would need to load the user back from the repository at the end.

Making gatling generate random data per request using a feeder

I'm trying to get gatling to create random data per POST request. I've followed a few posts on stackoverflow and other places. I came up with this scenario -
def randomUuid = UUID.randomUUID().toString
val feeder = Iterator.continually(Map("user" -> randomUuid))
def createPostRequest = {
http("createuser")
.post("http://jsonplaceholder.typicode.com/posts")
.body(StringBody("${user}"))
.check(status.is(201))
}
val scn = scenario("some load test")
.feed(feeder)
.forever(exec(createPostRequest))
setUp(scn.inject(atOnceUsers(1)))
.maxDuration(20 minutes)
However, when I run this code it just calls my feeder once to create a single UUID and just re-uses the same UUID throughout the load test.
I created the code above after following this thread. I'm using gatling 2.2.5. Here's my sbt config -
import sbt._
object Dependencies {
private val gatlingHighcharts = "io.gatling.highcharts" % "gatling-
charts-highcharts" % "2.2.5" % "test"
private val gatlingTest = "io.gatling" % "gatling-test-framework" % gatlingHighcharts.revision % "test"
val gatlingDependencies = Seq(gatlingHighcharts, gatlingTest)
}
As you don't call feed inside a loop, typically your forever one, you will indeed only generate one single value per virtual user.
If what you want is to have unique values per loop iteration, move the feed call inside the loop.
in your setUp, you're only creating one user - so your scenario is only getting executed once, meaning that 'feed' only occurs once before you start looping over your request.
change your scenario to be
val scn = scenario("some load test")
.feed(feeder)
.exec(createPostRequest)
and make your setUp (replacing 100 with whatever number of users you want)
setUp(scn.inject(atOnceUsers(100)))

How do i pass ## separated values in Scala?

Consider the following scenario:
["123##456","789##101112","131415##161718","192021##222324"]
first-id: 123, second-id: 456...
I get the above as two different sets of ids in the JSON payload of my response.
Saving the values via
.check(jsonPath("$.data[*].Id").findAll.saveAs("Id"))
works perfectly fine for me.
But now I need to pass the above-mentioned ids in the next request of post method, which comes as
["123##456","789##101112","131415##161718","192021##222324"]
So how to achieve that? If you could explain with an example please?
You could use split, something like:
var data = Array("123##456","789##101112","131415##161718","192021##222324");
for(i <- 0 until data.length){
var ids = data(i).split("##");
println("first id is: " + ids(0));
println("second id is: " + ids(1));
}

Saving session attribute in a list

I would like to save a session attribute in a list in my gatling simulation. What am trying to do is to get all the values of my JSON who are defined in a CV file and write it in a file. In my example below "test" is always equal to the value of the first jsonPath.
Here what I am doing:
val scn1 = scenario("[SCENARIO] GET")
.repeat(Nbproduct-1, "counter") (
feed(csv(CSV).circular)
.exec(http("get JSON")
.get(url_1")
.check(jsonPath("""$.${meta_ref}""").find.saveAs("test")))
.pause(1)
.exec(session => {
writer.write("\""+session("meta_cts").as[String]+"\":\"" + session("test").as[String]+"\",\n")
session
}
)
I also tried this but it get the value of the counter...
.check(jsonPath("""$.${meta_ref}""").find.saveAs("""jdd_value("${counter}")""")))
Thanks for the help!
Feeders are shared datasources, so first user will pop the first record, second user the second record, etc...
Then, it's not possible to define checks at runtime (depending on some entries in a file). All DSL components are builders that are only resolved once when the Simulation is loaded.