Groovy Script assert on Key/Value pairs in SOAP UI XML response - groovy

I am using Ready API/SOAP UI. I added a SOAP request and I get a SOAP response XML. My response object has up to 40 Key/Value pairs.
I have functional tests to specifically test each.
Loop through the whole ArrayOfObjects and Assert if the Key exists and if it exists assert the value.
Can I get a working solution for this scenario. I am unable to do assert on the output object.
SOAP structure looks like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ArrayOfallObjects>
<ArrayOfObjects>
<Key>Key1</Key>
<Value>Value1</Value>
</ArrayOfObjects>
<ArrayOfObjects>
<Key>Key2</Key>
<Value>Value2</Value>
</ArrayOfObjects>
---------------
<ArrayOfObjects>
<Key>Key40</Key>
<Value>Value40</Value>
</ArrayOfObjects>
</ArrayOfallObjects>
</soap:Body>
</soap:Envelope>
And I am using groovy script snippet as below
//Code Snippet Starts//
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def request = context.testCase.getTestStepByName("RequestName")
def responseCurrentHolder = groovyUtils.getXmlHolder( request.name +"#Response")
responseCurrentHolder.namespaces["ns1"] = "https://test.com"
def nodes = responseCurrentHolder.getDomNodes( "//ns1:Response/ns1:Result/ns1:ArrayOfallObjects/ns1:ArrayOfObject/*" )
def nodeCount = responseCurrentHolder.getNodeValues("//ns1:Response/ns1:Result/ns1:ArrayOfallObjects/ns1:ArrayOfObject/ns1:Key").length
def object = [:]
for (def nodeIndex = 1; nodeIndex <= nodeCount; nodeIndex++) {
def nodeKey = responseCurrentHolder.getNodeValues("//ns1:Response/ns1:Result/ns1:ArrayOfallObjects/ns1:ArrayOfObject[$nodeIndex]/ns1:Key/text()")
def nodeValue = responseCurrentHolder.getNodeValue("//ns1:Response/ns1:Result/ns1:ArrayOfallObjects/ns1:ArrayOfObject[$nodeIndex]/ns1:Value/text()")
object.put( nodeKey,nodeValue)
}
log.info "Object =" +object
// Code snippet ends//
And the object looks like:
Object =[[Key1]:Value1, [Key2]:Value2, and so on upto --,[Key40]:Value40]

You can use Script Assertion for the same soap request test step to verify the same without adding additional Groovy Script test step.
Not sure if above sample has the same xml structure (if not exact). Otherwise, adopt the changes to suit your need.
Here is the approach:
Since there is complex data to be verified, and there is key, value pattern; so define a map as expected data like you pointed in the last.
Read the xml response, and create similar map out of it. At times, it may require to sort the retrieved data by key (or other criteria based on the data).
Then check if both expected and actual data.
Script Assertion:
//Define expected data; using few elements as sample
def expectedMap = [Key1: 'Value1', Key2: 'Value2', Key40: 'Value40']
//Check if there is response
assert context.response, 'Response is empty or null'
//Parse the response
def xml = new XmlSlurper().parseText(context.response)
//Extract the data, create actual map and sort by key
def actualMap = xml.'**'.findAll {it.name() == 'ArrayOfObjects' }.collectEntries {[(it.Key.text()): it.Value.text()]}​?.sort {it.key}
log.info actualMap
assert expectedMap == actualMap
You can quickly try it online demo

The below code first get all keys in an array(x) and all values in another array
y(x). You may add them in a map if not you can directly assert values
The below is one of the easiest and simpler way of validating key value pair
Just replace the 'First Step' with the name of the step where response is generated
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def response = groovyUtils.getXmlHolder("First Step#Response")
def x = response.getNodeValues("//*[local-name()='ArrayOfObjects']//*[local-name()='Key']")
for ( def keys in x)
{
log.info keys
}
def y = response.getNodeValues("//*[local-name()='ArrayOfObjects']//*[local-name()='Value']")
for ( def values in y)
{
log.info values
}
log.info "total keys are " + x.size()
for(int i = 0 ; i < x.size() ; i++)
{
log.info " key = " + x[i] + " Value = " + y[i]
}
Here is the result when i ran the above script
Sat Oct 28 14:41:57 IST 2017:INFO:Key1
Sat Oct 28 14:41:57 IST 2017:INFO:Key2
Sat Oct 28 14:41:57 IST 2017:INFO:Key40
Sat Oct 28 14:41:57 IST 2017:INFO:Value1
Sat Oct 28 14:41:57 IST 2017:INFO:Value2
Sat Oct 28 14:41:57 IST 2017:INFO:Value40
Sat Oct 28 14:41:57 IST 2017:INFO:total keys are 3
Sat Oct 28 14:41:57 IST 2017:INFO: key = Key1 Value = Value1
Sat Oct 28 14:41:57 IST 2017:INFO: key = Key2 Value = Value2
Sat Oct 28 14:41:57 IST 2017:INFO: key = Key40 Value = Value40

Related

soap ui dynamic value from request content

I have a SOAP request which has dynamic values generated by random method. How to capture these generated values to log?
My SOAP request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
<web:ChangeLengthUnit>
<web:LengthValue>${=(int)(Math.random()*9999)}</web:LengthValue>
<web:fromLengthUnit>Inches</web:fromLengthUnit>
<web:toLengthUnit>Centimeters</web:toLengthUnit>
</web:ChangeLengthUnit>
</soap:Body>
</soap:Envelope>
Groovy script:
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
Above groovy script is giving output as below:
Wed Oct 18 14:55:13 SGT 2017:INFO:[${=(int)(Math.random()*9999)}]
Actual value of LengthValue tag = 3490, How to get this value ?
It can easily read from RawRequest property using Script Assertion for the same request step.
assert context.rawRequest, 'Request is empty or null'
def xml = new XmlSlurper().parseText(context.rawRequest)
def actualValueInTheRequest = xml.'**'.find{it.name() == 'LengthValue'}?.text()
log.info "Value for LengthValue in the actual request is : $actualValueInTheRequest"
I think what you're doing is getting the LengthValue from the request 'template' not what SoapUI has actually passed to the web service.
In your example, you have...
def stepReq = tStep.getProperty("Request").getValue()
The request is what you see in SoapUI that includes your vars, e.g. ${myVar}. I think what you're after is the 'raw request'.
In SoapUI, run the request and after it has ran, you should see a tab labelled 'Raw Request'. This is what SoapUI actually sends to the web service, in here you'll see that the vars have been evaluated and will show the value, which is what you are after.
I've taken your example and made some mods it. I haven't tested it, but it should help you.
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
// CHA MOD - Can only get raw request after running the step.
def rawRequest = context.expand( '${ChangeLengthUnit#RawRequest}' )
//CHA MOD - Quick look at the rawRequest...
log.info(rawRequest);
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
//CHA MOD - Get the length from the raw request...
holder = groovyUtils.getXmlHolder( rawRequest.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
You are getting value from the actual request. Try to get the data from RawRequest
use below code
def holder = groovyUtils.getXmlHolder(mentionThenameofthestep#RawRequest)
The above code will point to Raw request of your teststep which contains actual value passed during execution instead of "${=(int)(Math.random()*9999)}"

SOAP UI - How to Capture REST raw Response in a file

I am trying to capture the raw response for REST (POST) API call into a file using groovy Script.
I can see the response as below in RAW, but when file is produced it is blank.
REST Response:
HTTP/1.1 401 Unauthorized
content-length: 0
Date: Tue 12 jul 2016 12:12:12gmt
WWW-Autheticate: OAuth
Server: Jetty (8.1.17V20150415)
I am using SOAP UI version 5.2.
Any help appreciated.
Groovy Script:
def Date startTime = new Date()
File it=new File("Result")
def cur_Time = startTime.getMonth()+1 + "_" + startTime.getDate()
cur_Time = cur_Time + "_" + startTime.getHours() + startTime.getMinutes() +startTime.getSeconds()
def fileName = it.name + "_" + cur_Time
//Request File
def myXmlRequest="C:\\ConnectivityResults\\"+ "Rest_Request" + fileName+".xml"
def request=context.expand('${Testcasename#Request}')
def req = new File (myXmlRequest)
req.write(request,"UTF-8")
//Response File
def myXmlResponse="C:\\ConnectivityResults\\"+ "Rest_Response" + fileName+".xml"
def response=context.expand('${Testcasename#Response}')
def res = new File (myXmlResponse)
res.write(response,"UTF-8")
The problem isn't probably in your Groovy script, the problem is simply that your request is incorrect and nothing is returned as response. Based on the http-headers you show in the question:
HTTP/1.1 401 Unauthorized
content-length: 0
Date: Tue 12 jul 2016 12:12:12gmt
WWW-Autheticate: OAuth
Server: Jetty (8.1.17V20150415)
You're receiving an 401 Unauthorized response instead of 200 OK, and based on the Content-lenght which is 0. It's normal that your response is blank, so there is no content to save in file.
EDIT BASED ON COMMENT
If you want also to save the http-headers in a file, you can add the follow snippet to your Groovy script:
def fileName = ...
// http-headers file
def httpHeadersFilePath ="C:/ConnectivityResults/Rest_Request${fileName}.txt"
def ts = testRunner.testCase.getTestStepByName('Testcasename')
def headers = ts.getTestRequest().response.responseHeaders
def httpHeaderFile = new File(httpHeadersFilePath)
httpHeaderFile.text = ''
headers.each { key, value ->
httpHeaderFile.append("${key}:${value}\n",'UTF-8')
}
Hope it helps,
Sorry about the late...
There's a simple way to take it and record in a file, using Groovy Script on your SoapUI:
#Take the Raw Request into a variable "request":
def request = context.expand( '${Request 1#RawRequest}' )
#Take the Raw Response into a variable "response":
def response = context.expand( '${Request 1#Response}' )
#Create and fill a file "MyFile.json" whit the variables values:
new File( "C:/foo/bar/MyFile.json" ).write( request + response, "UTF-8" )
Hope that's useful.

How to get only value of sql query without header using groovy

I tried to fetch only DB value using groovy script but result includes the value along with header.
def res = con.rows("select fkuserid from tblUserCardDetail where cardValue='111633072'" )
log.info "The User ID from DB is :" + res
Result is coming like this :
Mon Apr 25 06:51:07 PDT 2016:INFO:The User ID from DB is :[[fkuserid:2951]]
I want only value : 2951
When Groovy SQL returns a result, it returns it as a Map-like object, a GroovyRowResult. Since you're using rows() you're getting a list of GroovyRowResults.
If the query will always return a single record (or nothing at all), then you can use firstRow() instead of rows(). Then, you can access the fkuserid property/key to get the value:
def res = con.firstRow("select fkuserid from tblUserCardDetail where cardValue='111633072'" )
log.info "The User ID from DB is :" + res.fkuserid

date method not working properly in groovy

i have this
class MainController {
def test = {
def day1 =1
def month1 = 10
def year1 = 2011
def date1 = new Date(year1 ,month1, day1);
}
}
But the OutPut is
Wed Nov 01 00:00:00 PKT 3911
Why its 3911 , shouldnt it be 2011 ??
Any solution
Thanks
Read the Date API of this deprecated constructor. You must pass in the year-1900. Also, the month is zero-based (also in the API docs).
That information was also shown in my answer to one of your previous questions.

Groovy : Dates not being calculated correctly? Using TimeCategory

can anyone tell me why these aren't being calculated correctly. I'm trying to add 1 second to the time and it seems to be adding 60 milliseconds when I apply formatting?
import java.text.*
import java.util.*
import groovy.time.TimeCategory
def xmlSlurper = new groovy.util.XmlSlurper()
// Get the previous total for number of journals
def journalCountProp = testRunner.testCase.getTestStepByName("Properties")
def journalCountTotal = journalCountProp.getPropertyValue( "journalCount" )
log.info " 1. Previous JournalCount from last run: "+journalCountTotal
def lastDateProp = testRunner.testCase.getTestStepByName("Properties")
def lastDateHolder = lastDateProp.getPropertyValue( "journalQueryDate" )
log.info " 2. Previous lastDate from last run: "+lastDateHolder
// Get the response for a given timeline
def response = xmlSlurper.parseText(context.expand('${GET Journal using JournalDate#Response}'));
def currentJournalCount = response.Journals.Journal.size()
log.info " 3. Number of Journals in this Run: "+currentJournalCount
//Getting the date from the last Journal (including an offset as the array count starts at 0)
def lastDate = response.Journals.Journal[currentJournalCount-1].CreatedDateUTC
log.info " 4. CreatedDate from last journal in this response: "+lastDate
//log.info response.Journals.Journal[currentJournalCount-1].CreatedDateUTC
def newdate = Date.parse("yyyy-MM-dd'T'HH:mm:ss.mmm",lastDate.toString())
log.info "dateBeforeChange: "+newdate.format("yyyy-MM-dd'T'HH:mm:ss.mmm")
use(TimeCategory){
newdate = newdate+1.seconds
}
log.info "date After Change: "+newdate.format("yyyy-MM-dd'T'hh:mm:ss.mmm")
log.info " 5. "+newdate.format("yyyy-MM-dd'T'HH:ss:mmm")
OUTPUT:
CreatedDate from last journal in this response: 2007-03-29T23:19:52.073
dateBeforeChange: 2007-03-30T00:13:52.013
date After Change: 2007-03-30T12:13:53.013
I can't figure it out?!!
Cheers,
- Richard
HH means "hour in a day (0-23)", whereas hh means "hour in am/pm (1-12)".
See the SimpleDateFormat ApiDoc for a reference (SimpleDateFormat is used under the hood).

Resources