Pass variable as attribute to XML body - scala

I am creating a Gatling load test in Scala and I wish to create a HTTP POST request with attribute.
val getServiceCall = http("get service call")
.post("/MyService")
.headers(header)
.body(ElFileBody("templates/GetServiceCallRqTemplate.xml"))
.check(status.is(200))
And this is a snippet from my xml:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<pus:GetServiceCallRq>
<com:header>
<com:type>pus:GetServiceCallRq</com:type>
<com:timestamp>timestamp</com:timestamp>
<com:source>source</com:source>
<com:destination>destination</com:destination>
<com:serverNode>serverNode</com:serverNode>
</com:header>
<pus:body>
<pus:reference>${reference}</pus:reference>
....
I would like to pass the ${reference} attribute from a variable creating within my code - and not from a csv file.
How is it possible to pass it as a request param?

using a feeder (csv file) is not the only way to get a value into a session parameter.
you could also set the value manually via a session action
exec(session => session.set("reference", "ref0001"))
or via a check on an earlier request (whatever is in the 'ref' key in the response gets saved to the ${reference} variable
exec(
http("setupReq")
.get("someURL")
.check(
jsonPath("$.ref").saveAs("reference")
)
)
or even by creating your own custom feeder - for example, if you just wanted to generate random references
//somewhere at the top of your scala class
private val refs = Iterator.continually(
Map("reference" -> (Random.alphanumeric take 10 mkString).toUpperCase())
)
//then later in your scenario...
.feed(refs) //will put a new random string into ${reference}
//then make your "get service call" request

Related

How to set different protocol for each user (threads running) in gatling

I am trying to create a performance test suite where i have array of ID's that will be picked in random. For each ID , there is a designated auth_token assigned .
In the protocol , if i pass the method where the random ID's would take , it always sets it to that particular ID for the entire operation .
I am expecting something like , i am defining 10 virtual users and for each user the protocol should change the ID and continue the scenario execution .
Currently Gatling is setting the protocol at the first and uses the same protocol for all the 10 users.
id = random.generate //generate random id
authHeader = Method(id);
def method (id:String) : String{
if(id=="id1")
return token1
else if(id=="id2")
return token2
""
}
val httpProtocol = http.baseUrl(baseURI)
.acceptHeader(header)
.authorizationHeader(authHeader)
.contentTypeHeader(contentType)
.userAgentHeader(agentHeader)
val scn1: ScenarioBuilder = scenario("name")
.exec(http("scenario1")
.post(device_context)
.body(payload)
.check(status.is(202)))
setUp(scn1.inject(atOnceUsers(2)).protocols(httpProtocol))```
In the above code i need the suite to run for 2 different id.
To make this work, you're going to have to use a session variable to hold your authHeader. The DSL methods define builders that are only executed once - which explains what you're seeing.
The best way to do this would be to construct a feeder to hold your ids and auth tokens (I'm assuming you're not using the id anywhere else)
So define a feeder that maps a key (just a string) to a map that contains the id and auth token
//a list of strings to hold the auth tokens
private val ids = List(Map("id" -> "id1", "auth" -> "token1"), Map("id" -> "id2", "auth" -> "token2"), ...)
//the feeder to put a random token into the session
private val idFeeder = Iterator.continually(Map("id" -> Random.shuffle(ids).head))
now when you call .feed on idFeeder you get a random Map that has keys for "id" and "auth" in the session variable "id"
so update your scenario to use the feeder and set an Authorization header (and remove .authorizationHeader from your protocol definition)
val scn1: ScenarioBuilder = scenario("name")
.feed(idFeeder)
.exec(http("scenario1")
.header("Authorization", "${id.auth})"
.post(device_context)
.body(payload)
.check(status.is(202)))
in your body you can access the user id string with "${id.id}"
alternatively you could update your protocol definition to have the ${id} reference, but I find it nicer to have the feeder value used in the same block as the call to .feed

Gatling pass feeder as a parameter to object

I have a Gatling script with few objects that I use for my tests. One of the objects is used to authenticate users and users are passed to test using a feeder. The feeder is now defined on top in the beginning of the simulation class like this:
val feeder = csv("users.csv").circular
The feeder provides pairs of usernames and passwords. The object looks like:
object Auth {
val login = {
feed(feeder)
.exec(http("get_auth_token")
.post("/get_auth_token")
.body(StringBody("""{
"username": "${username}",
"password": "${password}"
}""")).asJSON
// this check extracts accessToken from JSON received in response
.check(
status.find.in(200,304,201,202,203,204,205,206,207,208,209),
jsonPath("$.response_body.access.token").saveAs("accessToken"),
jsonPath("$.response_body.refresh.token").saveAs("refreshToken")
)
).exitHereIfFailed
}
val refreshAuthToken = {
exec(http("refresh_auth_token")
.post("/refresh_auth_token")
.header("Authorization", "Bearer ${refreshToken}")
.check(
status.find.in(200,304,201,202,203,204,205,206,207,208,209),
jsonPath("$.response_body.access.token").saveAs("accessToken")
)
).exitHereIfFailed
}
}
Then I have a scenario that looks like:
val myScenario = scenario("My test")
.exec(Auth.login)
// Do some stuff here
.exec(Auth.refreshAuthToken)
// Do more stuff here
Then I have a setup that runs this single scenario.
What I would like to have is additional scenario that will run alongside with the get additional scenario that will run alongside with myScenario. This scenario will also perform Auth.login, but I want it to use a different set of users - so I need to have two separate feeders that will be passed to Auth.login from scenario. Can someone suggest how this can be achieved?

Rest Assured API testing - Pass a Json Object as parameter to a get request

REST Assured Testing -
How to use delete request to delete the Workspace from this url
http://in-kumaran2-1:8080/devops-workbench-web/rest/api/workspace/delete/{projectId}
given the request
given().when().delete(url,JSON body);
Where Sample Request JSON body is given below
{"name":"newworkspace","workspaceFlow":"Open
Sorce","versionControl":"SVN","featureManagement":"JIRA","defectManagement":"","buildAutomation":"Selenium","deploymentAutomation":"","buildRepository":"Nexus","codeQualityTools":"SonarQube","automatedTestingTools":"Selenium","environmentProvision":"Puppet","environmentConfiguration":"Puppet","projectId":{"id":"56cebe578850d51c6fe07684","name":"wbproject","description":"wbproject","processTemplate":"Agile","projectManager":"Anil","projectStartDate":1454284800000,"projectEndDate":1475193600000,"remarks":null,"accountId":{"id":"56cebe218850d51c6fe07683","accountName":"workbench","accountDescription":"workbench
account"}}}
projectID has another Object {"id": "56cebe578850d51c6fe07684" ....} How to pass this projectId in the delete Request
actually, i have passed json object like below:
Response res =given().
content(jo). //jo is the json object to pass with the url.
with().
contentType("application/json").
header("Content-Type", "application/json").
when().
post(settings.getApiUrl()); //this is the url, i use post method
and jo is something like this:
JsonObject jo = new JsonObject();
jo.addProperty("username", "abc");//key and value
jo.addProperty("password", "abc");//key and value
u may try something like this.i used here as header u may send it as param.
URL is: http://example.com/building
My Query Strings are :
globalDates:{"startMs":1473672973818,"endMs":1481448973817,"period":90}
limitTo:6
loadTvData:true
startFrom:0
userId:5834fb36981baacb6a876427
Way to pass Query String Parameters in GET url using Rest Assured like this :-
when() .parameter("globalDates","startMs","1474260058054","endMs","1482036058051","period","90")
.parameters("limitTo","6")
.parameters("loadTvData","true")
.parameters("startFrom","0")
.parameters("userId","5834fb36981baacb6a876427");

Gatling 2 dynamic queryParam on each request

I am trying to run a load test using Gatling 2. I need to generate one of the query parameters dynamically on each request.
My scenario is defined like this:
val scn = scenario("Load Test Scenario")
.exec(
http("Test API")
.post(url)
.body(StringBody("Some XML"))
.queryParam("x", DigestUtils.md5Hex(generateX().getBytes("UTF-8")))
)
def generateX() : String = {
// generate random string and return
}
This only calls generateX once and uses the result in each request. Is there anyway to have the generateX call on every request?
You have to pass a function, not a value. See Gatling documentation about Expression.
Here, you can just discard the session input parameter as you don't use it, so you can simply write:
.queryParam("x", _ => DigestUtils.md5Hex(generateX().getBytes("UTF-8")))

SoapUI - Automatically add custom SOAP headers to outgoing request

So what I want to do is to automatically add SOAP header to every request that is generated in SoapUI as I've got hundreds of them and doing this manually is annoying.
Lets say that this is my example request generated from the WSDL which looks like that:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pol="http://something">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<pol:GetSomething>
<tag1>3504</tag1>
<tag2>ALL</tag2>
</pol:GetSomething>
</soapenv:Body>
</soapenv:Envelope>
and when I make the request I want SoapUI to modify it to look like that:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pol="http://something">
<soapenv:Header>
<token xmlns="ns1">${TOKEN}</token>
<user xmlns="ns2">user</user>
<system xmlns="ns3">system</system>
</soapenv:Header>
<soapenv:Body>
<pol:GetSomething>
<tag1>3504</tag1>
<tag2>ALL</tag2>
</pol:GetSomething>
</soapenv:Body>
</soapenv:Envelope>
Is it possible in SoapUI?
In your testCase you can add a first step of type Groovy Script, in this script you can manipulate each request to add necessary elements on <soap:Header>, I give you an example that works for me:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def tcase = testRunner.testCase ;
// get total number of testSteps
def countTestSteps = tcase.getTestStepList().size();
// start with 1 to avoid groovy script testStep
for(i=1;i<countTestSteps;i++){
// get testStep
def testStep = tcase.getTestStepAt(i);
// get request
def request = testStep.getProperty('Request').getValue();
// get XML
def xmlReq = groovyUtils.getXmlHolder(request);
// get SOAPHEADER
def soapHeader = xmlReq.getDomNode("declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/'; //soap:Header")
// document to create new elements
def requestDoc = soapHeader.getOwnerDocument()
// create new element
def newElem = requestDoc.createElementNS(null, "element");
// insert in header
soapHeader.insertBefore(newElem, soapHeader.getFirstChild());
// now put your new request in testStep
log.info xmlReq.getXml();
testStep.setPropertyValue('Request', xmlReq.getXml());
}
This sample code only add one new element on the <soap:header>, but you can modify it to add attributes, text content and more nodes. You can also take a look at:
dynamically create elements in a SoapUI request | SiKing