Groovy script - Sum two values of REST response and pass the sum on to the next request
SOLVED- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Groovy script - Sum two values of REST response and pass the sum on to the next request
Hi!
I'm currently utilizing ReadyAPI for functional tests of our API.
I am already using "simple" property transfer / Get Data to pass on a value from one test step REST response to the next REST request like:
${TestStep1#Response#$['ABC']['Array'][0]['Price']['value']}
Now what I want to achieve is passing on the sum of two values of a response to the next request.
E.g. let's say Test Step 1 Response gives me the following data:
Now I want to pass on the sum of the prices (1.4 + 2 = 3.4) to a field of the next request.
I was told by Smartbear Support that this can be achieved using Groovy scripts but they do not offer customer support for scripts and I was referred to this Community form.
As I am totally new to Groovy Script and not sure about how to use it for my goal which isn't complex at all but again, I have never used Groovy Script before, I am asking if someone could help of an example of how this would look like?
Maybe also with an example if the values were returned in string format and I would need to parse them to Double first?
Thank you!
Solved! Go to Solution.
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Groovy script is a subset of Java and is really, really useful to learn. There's loads of on-line resources for using Groovy scripts.
In terms of what you want, here is the script. Create a Groovy script step, called "Add - Groovy Script" after your web service call and paste in the below....
def valueOne = "4"; // ${TestStep1#Response#$['ABC']['Array'][0]['Price']['value']};
def valueTwo = "8.2"; // ${TestStep1#Response#$['ABC']['Array'][1]['Price']['value']};
try {
def valueOneDouble = Double. parseDouble(valueOne);
def valueTwoDouble = Double. parseDouble(valueTwo);
def answer = valueOneDouble + valueTwoDouble;
log.info ("My Sum is ${valueOneDouble} + ${valueTwoDouble} = ${answer}");
def answerString = String.valueOf(answer);
// Put the answer into a custom property for the test case.
testRunner.testCase.setPropertyValue( "mySum", answerString );
// or simply return it....
return answerString;
} catch (NumberFormatException e) {
//the parseDouble failed and you need to handle it here.
}
Note : for example purposes, I've hard-coded values one and two and commented how you'd access them according to your question.
To use the answer in a subsequent step, you have options. You're already using Property Transfer, but I never have so I don't know if you can transfer the answer from a groovy script.
My example puts the answer into a custom property (like a global variable) at the test case level. You can then access this from another step. Look up custom properties on the SmartBear site.
You can also 'pull' the answer from the Groovy step directly into the subsequent step. If you go the step where you want the answer and edit the payload. When you want the value inserting, type...
${Add - Groovy Script#result}
When ReadyAPI is about to call the 'subsequent' step, it will then call the Groovy script and replace the ${} stuff with the actual value.
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi @ChrisAdams
Thank you very much for your help.
Unfortunately when trying to run the script as a test step, I am receiving the following error:
Here's the minimalistic script I configured:
def value = ${CheckContingentStartTimes#Response#$['ContingentStartTimes']['ContingentStartTime'][0]['Price']['value']};
log.info("${value}");
It seems to have an issue with how I adressed the field?
Though this notation is working when using it as a field in the request using the Get Data - dialog.
Thanks in advance for your assitance.
Best regards,
Markus
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Try wrapping context.expand around your variable.
E.g.
def value = ${CheckContingentStartTimes#Response#$['ContingentStartTimes']['ContingentStartTime'][0]['Price']['value']};
becomes....
def value = context.expand('${CheckContingentStartTimes#Response#$['ContingentStartTimes']['ContingentStartTime'][0]['Price']['value']}}');
But, if you have ReadyAPI then there is a better way....
In the Groovy window, put the cursor near the top and right-click. In the context menu, there is an option called 'Get Data'. Click it. You'll then get another window which will let you navigate through your test structure and actually select the value you want from the service call's response. It will then insert the correct value to access.
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@mrechberger , checkout below script. I am reading it from a file as I don't have a request to read it's response.
assumption behind my script is that you want to modify the response with new json array and "value" should be sum of 1.4+ 2.
import net.sf.json.groovy.*
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
//Read response from a file
jsonFile = "C:/Users/new2API/Downloads/response.txt"
def jsonResponse = new File(jsonFile).text
def parsedJson = new JsonSlurper().parseText jsonResponse
//if directly reading response from a previous REST Call
//Get response
//jsonResponse = context.expand('${'+ TestStepName +'#Response}').toString()
//parsedJson = new JsonSlurper().parseText jsonResponse
log.info parsedJson
//reading values from Json response and add
def valSum = 0
parsedJson.Items.each{
valSum = valSum + it.Price.value
}
/*
//modify earlier response to send as a payload
//here you are sending only one json array in the payload
parsedJson.Items.remove(0)
//update json nodes
parsedJson.Items[0].Description = 'ABC'
parsedJson.Items[0].Price.currencyCode = 'EUR'
parsedJson.Items[0].Price.value = valSum
//rebiuld json payload
def requestPayload = new JsonBuilder(parsedJson).toString()
log.info requestPayload
*/
//if you want add another json array then use this code
def itemJson = parsedJson.Items[0]
log.info itemJson
//add it to earlier response
def newJsonArray = parsedJson.Items + itemJson
//## Get Request Map ##//
def jsonMap = [:]
parsedJson.each{
jsonMap[it.key] = it.value
}
//define items map
def itemsMap = [:]
newJsonArray.each{
itemsMap[it.key] = it.value
}
// Replace items with new array//
jsonMap['Items'] = newJsonArray
//update json nodes
jsonMap.Items[2].Description = 'ABC'
jsonMap.Items[2].Price.currencyCode = 'EUR'
jsonMap.Items[2].Price.value = valSum
//rebiuld json payload
def requestPayload = new JsonBuilder(jsonMap).toString()
log.info requestPayload
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi @ChrisAdams
Thanks for the tip!
I was not aware that I could use the Get Data - dialog also in this window which makes it totally easier.
Just one minor correction to your sample:
The apostrophe has to be escaped using \
Like that:
def value = context.expand('${CheckContingentStartTimes#Response#$[\'ContingentStartTimes\'][\'ContingentStartTime\'][0][\'Price\'][\'value\']}}');
But anyways, that helped!
Thank you a lot!
Best regards,
Markus
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi @New2API
Thanks for your suggestion but Chris got me the needed answer.
Have a nice day!
Best regards,
Markus
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Get Data option save so much time. It's quick, clean and always correct. Creating your own paths can be tough to debug/fix.
