I want to compare some <key,values> in the jsonPath passed as HashMap<String,String>() data. How can we achieve it in gatling check ?
val hashMap = new HashMap[String,String]()
hashMap.put("foo", "bar")
OR can I simply check something like this ?
for (String key <- keyValue){
.check(jsonPath("$." + key.(is(hashMap.get(key)))))
}
OR
.check(jsonPath.containsAll(hashMap.keySet), jsonPath.containsAll(hashMap.valueSet))
Or can I use hamcrest or some other to compare this HashMap with JsonPath.
.exec(http("my testl").post("/some_url").headers(common_header).body(bodyPayLoad).
asJSON.check(status.is(200)).check(jsonPath("$",Matchers.hasItems(hashMap)).saveAs("response"))).exec(session => {
val responseValue = session.get("response").asOption[String]
println(testCase + " REST API Response :" + responseValue)
session
}).pause(10)
How can I achive it?
Related
I am new to scala and gatling . I am trying to fetch values from feeder and post zip file to service . but ${extensionId} is not been updated with fetched value instead it remain as ${extensionId} . Could some one please help me know If I miss some thing here .
def installExtension() =
exec(http("template - Install Extension")
.post(url + "/v1/extensions")
.basicAuth("jack", "password")
.headers(namespaceHeader)
// using testUtils to get InputStream conte
.body(InputStreamBody(TestUtils.toStream(hashMap.get("${extensionId}").getOrElse(null))))
.check(status.is( 201)))
class extmgrSimulations extends Simulation {
val extensionIds = csv(s"${Configuration.dataDirectory}/extensionId.csv").circular
val extMgrScenerio = scenario("extensionMgr - Scenario")
.during(Configuration.duration) {
exitBlockOnFail(
group("load-test") {
exec(
pace(Configuration.paceFrom, Configuration.paceTo),
feed(extensionIds),feed(extensionIds)
randomSwitch(
50.00 -> group("Install and delete") {
exec(
extmgrChain.installExtension(),
extmgrChain.deleteExtension(),
)
},
50.00 -> extmgrChain.listExtension()
)
)
}
)
}
That can't work. Gatling EL (the ${} syntax in strings) doesn't magically work anywhere. This is explained in the documentation.
Warning
This Expression Language only works on String values being passed to Gatling DSL methods. Such Strings are parsed only once, when the Gatling simulation is being instantiated.
For example queryParam("latitude", session => "${latitude}") wouldn’t work because the parameter is not a String, but a function that returns a String.
Also, queryParam("latitude", "${latitude}".toInt) wouldn’t because the toInt would happen before passing the parameter to the queryParam method.
The solution here would be to pass a function:
session => session("latitude").validate[Int].
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));
}
I'm trying to correlate or create a "Check" in Gatling load tool, but not sure how to do it. I Went through the advanced tutorial doc from official Gatling website but couldn't exactly find much on correlation of the dynamic value.
Below is the peice of code from my script
.feed(feeder)
.exec(http("EnterDetails")
.post("/events/review.action")
.headers(headers_6)
.formParam("userInfo.spgEmail", "")
.formParam("userInfo.title", "")
.formParam("userInfo.firstName", "${FirstName}")
.formParam("userInfo.lastName", "${LastName}")
.formParam("userInfo.address1", "Open")
.formParam("userInfo.address2", "")
.formParam("userInfo.city", "${City}")
.formParam("userInfo.state", "NYY")
.formParam("userInfo.country", "US")
.formParam("userInfo.zipCode", "10016")
.formParam("userInfo.primaryNoInfo.optedIn", "false")
.formParam("userInfo.phoneTwoInfo.optedIn", "false")
.formParam("userInfo.phoneThreeInfo.optedIn", "false")
.formParam("userInfo.primaryNoInfo.validInd", "Y")
.formParam("userInfo.phoneTwoInfo.validInd", "")
.formParam("userInfo.phoneThreeInfo.validInd", "")
.formParam("userInfo.phoneUseType1", "0")
.formParam("userInfo.primaryNoInfo.phoneNumber", "9876543211")
.formParam("userInfo.primaryNoInfo.extension", "")
.formParam("userInfo.country1", "US%28%2B1%29")
.formParam("__checkbox_userInfo.primaryNoInfo.oneTimeOptInPresent", "true")
.formParam("userInfo.phoneUseType2", "-1")
.formParam("userInfo.phoneTwoInfo.phoneNumber", "")
.formParam("userInfo.phoneTwoInfo.extension", "")
.formParam("userInfo.country2", "US%28%2B1%29")
.formParam("__checkbox_userInfo.phoneTwoInfo.oneTimeOptInPresent", "true")
.formParam("userInfo.phoneUseType3", "-1")
.formParam("userInfo.phoneThreeInfo.phoneNumber", "")
.formParam("userInfo.phoneThreeInfo.extension", "")
.formParam("userInfo.country3", "US%28%2B1%29")
.formParam("__checkbox_userInfo.phoneThreeInfo.oneTimeOptInPresent", "true")
.formParam("userInfo.email", "")
.formParam("userInfo.retypeEmail", "")
.formParam("userInfo.nonCCPayment", "true")
.formParam("userInfo.SPGNumber", "")
.formParam("userInfo.arrivalCarrier", "")
.formParam("userInfo.transportationNumber", "")
.formParam("userInfo.transportationArrTime", "")
.formParam("userInfo.hotelArrivalTime", "")
.formParam("userInfo.hotelDepartureTime", "")
.formParam("userInfo.SRequest", "")
.formParam("userInfo.IAgree", "true")
.formParam("__checkbox_userInfo.IAgree", "true")
.formParam("method%3Aexecute", "Review+Your+Reservation+"))
.pause(2)
.exec(http("ReviewREservation")
.get(uri3 + "/s01000706679492?AQB=1&ndh=1&pf=1&t=21%2F3%2F2016%2012%3A45%3A54%204%200&D=D%3D&fid=31A8BC73D5B8ACEB-2B64CD0ACE185774&ce=UTF-8&pageName=Review%20Reservation&g=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Freview.action&r=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Fselectcreate%21execute.action%3FselRoom%3D1&cc=USD&ch=StarGroups&server=StarGroups&c2=SOCIAL&c3=1603295001&c4=271&c5=SI&c6=YES&c8=en&s=1600x838&c=24&j=1.6&v=N&k=Y&bw=1042&bh=733&AQE=1")
.headers(headers_3))
.pause(7)
.exec(http("request_13")
.post("/events/confirm.action")
.headers(headers_6)
.formParam("method%3Aexecute", "Complete+Your+Reservation"))
.pause(4)
.exec(http("CompleteReservation")
.get(uri3 + "/s03623649917832?AQB=1&ndh=1&pf=1&t=21%2F3%2F2016%2012%3A46%3A5%204%200&D=D%3D&fid=31A8BC73D5B8ACEB-2B64CD0ACE185774&ce=UTF-8&pageName=Reservation%20Confirmation&g=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Fconfirm.action&r=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Freview.action&cc=CAD&purchaseID=20160421_734091125&ch=StarGroups&server=StarGroups&events=purchase&products=%3B271%3B1%3B100.00&c2=SOCIAL&c3=1603295001&c4=271&v4=20160421_734091125&c5=SI&c6=YES&c8=en&s=1600x838&c=24&j=1.6&v=N&k=Y&bw=1042&bh=733&AQE=1")
.headers(headers_3))
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
In The above code I have a dynamic Purchase ID in
.exec(http("CompleteReservation")
which gets generated from the server and needs to be correlated.
From The Gatling Documentation, I understand( correct me if I'm wrong) that we need the inspect element code to get the CSS path.(Shown Here).
Inspect Element
Please let me know how do we correlate .TIA.
In Gatling you have to use checks to extract a value from response. Take a look in documentation.
You can choose to use regex or xpath to extract value in tag. But in your case I'd recommend to use simple regex because IMO in your example response there are not tags or IDs where you can easily hook with xpath. I mean the way that the xpath expression will still remain simple and understandable. Next thing is to extract value into session and afterwards to use it.
Following is the example scenario extracting query path of URI from response received from example.com which is afterwards printed in console:
val scn = scenario("Checks")
.exec(
http("root")
.get("/")
.check(
// Extracting URI query path from response body via regexp and storing into session
regex("""www\.iana\.org/([a-z/]*)""").find.saveAs("queryPath")
)
)
// Printing the value from session
// Important thing to note is how you can access stored value from session
.exec { session =>
println(" QUERY PATH --> " + session("queryPath").as[String])
session
}
In your case your last part could look something like this:
.exec(http("CompleteReservation")
.get(uri3 + "/s03623649917832?AQB=1&ndh=1&pf=1&t=21%2F3%2F2016%2012%3A46%3A5%204%200&D=D%3D&fid=31A8BC73D5B8ACEB-2B64CD0ACE185774&ce=UTF-8&pageName=Reservation%20Confirmation&g=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Fconfirm.action&r=https%3A%2F%2Fstg.starwoodmeeting.com%2Fevents%2Freview.action&cc=CAD&purchaseID=20160421_734091125&ch=StarGroups&server=StarGroups&events=purchase&products=%3B271%3B1%3B100.00&c2=SOCIAL&c3=1603295001&c4=271&v4=20160421_734091125&c5=SI&c6=YES&c8=en&s=1600x838&c=24&j=1.6&v=N&k=Y&bw=1042&bh=733&AQE=1")
.headers(headers_3))
.check(
regex("""Your confirmation number is (\d+)""") // Regular expression with group which represents confirmation number.
.find
.saveAs("confirmationNumber") // Now the extracted regexp group is stored in session under "confirmationNumber" as name.
)
// Missing, check, transformation or use of value from session
I don't know your usage of extracted value thus it's missing in snippet above . But I hope that you will already have an idea how to handle responses and how to use the extracted values next.
I hope that it helps.
There is a web service returning array of something
{"apps": [{"name": "one"}, {"name": "two"}]}
In my code I want to iterate every name
val request = WS.url(s"http://localhost:9000/getData")
val json = request.get.map { response =>
(response.json \ "apps" \\ "name")
}
json.foreach(println)
However all my attempts return single record
// Expect
one
two
// Actual
ListBuffer("one", "two")
First of all, the neat solution here would be:
val request = WS.url(s"http://localhost:9000/getData")
request.get.map { response =>
val names = (response.json \ "apps" \\ "name")
names.foreach(println)
}
Secondly, if you don't want to get confused about the types, you should change your naming standards. For a Future object, you may start with the prefix future, for an Option, it could start with maybe, etc. If you do so, the problem in your example will be more obvious:
val request = WS.url(s"http://localhost:9000/getData")
val futureJson = request.get.map { response =>
(response.json \ "apps" \\ "name")
}
futureJson.foreach(println) // you call foreach for a Future, not for a List
Thirdly, why would Future trait have a method called foreach? I think that's confusing for beginners and even mid-level developers. We know from other languages that, foreach means iterate over a list of objects. In Scala, it is considered part of "Monadic operations" which is still a gray area for me :), but the comment for Future.foreach in Scala source is this:
/** Asynchronously processes the value in the future once the value becomes available.
*
* Will not be called if the future fails.
*/
def foreach[U]
Your value of json is actually a Future[Seq[JsValue]], so when you foreach over the future you get the entire list back. You would need an additional foreach to iterate over the list of values.
I have standard list of objects which is used for the some analysis. The analysis generates a list of Strings and i need to look through the standard list of objects and retrieve objects with same name.
case class TestObj(name:String,positions:List[Int],present:Boolean)
val stdLis:List[TestObj]
//analysis generates a list of strings
var generatedLis:List[String]
//list to save objects found in standard list
val lisBuf = new ListBuffer[TestObj]()
//my current way
generatedLis.foreach{i=>
val temp = stdLis.filter(p=>p.name.equalsIgnoreCase(i))
if(temp.size==1){
lisBuf.append(temp(0))
}
}
Is there any other way to achieve this. Like having an custom indexof method that over rides and looks for the name instead of the whole object or something. I have not tried that approach as i am not sure about it.
stdLis.filter(testObj => generatedLis.exists(_.equalsIgnoreCase(testObj.name)))
use filter to filter elements from 'stdLis' per predicate
use exists to check if 'generatedLis' has a value of ....
Don't use mutable containers to filter sequences.
Naive solution:
val lisBuf =
for {
str <- generatedLis
temp = stdLis.filter(_.name.equalsIgnoreCase(str))
if temp.size == 1
} yield temp(0)
if we discard condition temp.size == 1 (i'm not sure it is legal or not):
val lisBuf = stdLis.filter(s => generatedLis.exists(_.equalsIgnoreCase(s.name)))