How to pick up child element of specific parent element in Script Assertion? - groovy

I have the following XML example which shows there are multiple occurrences of node 'ProductCode' which fall under both nodes 'PrevHospProduct' and also under 'PrevExtrasProducts'.
<ns2:PrevHospProducts>
<ns2:PrevHospProduct>
<ns2:ProductCode>D00</ns2:ProductCode>
<ns2:ExcessPaid>Yes</ns2:ExcessPaid>
</ns2:PrevHospProduct>
<ns2:PrevHospProduct>
<ns2:ProductCode>900</ns2:ProductCode>
</ns2:PrevHospProduct>
</ns2:PrevHospProducts>
<ns2:PrevExtrasProducts>
<ns2:PrevExtraProduct>
<ns2:ProductCode>00A</ns2:ProductCode>
</ns2:PrevExtraProduct>
</ns2:PrevExtrasProducts>
For this test I am only interested in the values in 'ProductCode' which are a child of 'PrevHospProduct'. I am not interested in any of the values under 'PrevExtrasProducts'.
I have the following Groovy Script Assertion in SoapUI to pick up values in 'ProductCode' but the test is failing as the actual results are also returning 'D00', '900' and '00A' from the examples response. I only want the expected results to pick values 'D00', '900'.
def expectedCodes = ['D00','900']
def pxml = new XmlSlurper().parseText(context.response)
def actualCodes = pxml.'**'.findAll{it.name() == 'ProductCode' }*.text() as List
assert expectedCodes.sort() == actualCodes.sort()

First need to find the parent node i.e., PrevHospProduct and then get the ProductCode.
Here is the script assertion:
def expectedCodes = ['D00','900']
def pxml = new XmlSlurper().parseText(context.response)
def actualCodes = pxml.'**'.findAll{it.name() == 'PrevHospProduct'}*.ProductCode*.text() as List
log.info actualCodes
assert expectedCodes.sort() == actualCodes.sort()

Related

SOAPUI Square brackets around my actual results causing assert to fail

I am writing a Groovy script assertion which is verifying a value from a previous JDBC response step against a value contained in a SOAP response.
When I run my scripts I can see that both values are coming back the same but the actual result value (from the SOAP response) is surrounded by square brackets which in turn makes the assert fail. I'm guessing this is something to do with one being a string and one not?
How do I either strip out the square brackets from actual result or get them added to the expected result value to ensure the assert passes?
Below is my assert script.
Expected result is 001
Actual result is [001]
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( messageExchange.responseContent )
def pxml = new XmlSlurper().parseText(context.response)
//grab the expected result from jdbc response
def expectedCodes = context.expand( '${JDBC Request#ResponseAsXml#//*:TW304_PRODHIST.PRODUCT_1}' )
//grab the actual result from the SOAP response
def actualCodes = pxml.'**'.findAll{it.name() == 'CurrHospProductCode'}*.text()
assert expectedCodes == actualCodes
log.info expectedCodes
log.info actualCodes
Because you are expecting a single value as expected where as you are getting an array with single element in it.
You can do it as below if that is right :
assert expectedCodes == actualCodes[0]
On a side note, you may have to check carefully are you really expecting single value only or if there is possible to get list of values.
EDIT: based on your script.
findAll gives you list as result. If you are expecting single element in the xml, then you can change it to find and then you actual code should work as it is.

Identifying multiple values in SOAP UI response with Groovy

I was recently helped through a problem here where I wanted to identify multiple values from a SOAPUI response. This was successfully answered here.
I tried to take this same approach to a new problem I have. This time I would like to pick up 4 values from each section to use as my expected results.
Below is an example of my response that I want to run the assert expected results against:
<ns1:LimitAndUsageDetailsList>
<ns2:LimitAndUsageDetails xmlns:ns2="http://www.">
<ns2:LimitCode>022</ns2:LimitCode>
<ns2:LimitCodeDesc>APPLIANCES</ns2:LimitCodeDesc>
<ns2:LimitType>N</ns2:LimitType>
<ns2:LimitBenefit>500.0</ns2:LimitBenefit>
<ns2:LimitBenefitUsed>0.0</ns2:LimitBenefitUsed>
<ns2:LimitBenefitAvailable>500.0</ns2:LimitBenefitAvailable>
<ns2:LimitBenefitService>0</ns2:LimitBenefitService>
<ns2:LimitBenefitUsedService>0</ns2:LimitBenefitUsedService>
<ns2:LimitBenefitAvailableService>0</ns2:LimitBenefitAvailableService>
<ns2:QualifyingPeriodIndicator/>
<ns2:ClaimIndicator>B</ns2:ClaimIndicator>
<ns2:LimitPeriod>1</ns2:LimitPeriod>
<ns2:LimitPeriodType>C</ns2:LimitPeriodType>
<ns2:LimitScale>INDIV</ns2:LimitScale>
</ns2:LimitAndUsageDetails>
<ns2:LimitAndUsageDetails xmlns:ns2="http://www.">
<ns2:LimitCode>023</ns2:LimitCode>
<ns2:LimitCodeDesc>NEBULISER</ns2:LimitCodeDesc>
<ns2:LimitType>N</ns2:LimitType>
<ns2:LimitBenefit>0.0</ns2:LimitBenefit>
<ns2:LimitBenefitUsed>0.0</ns2:LimitBenefitUsed>
<ns2:LimitBenefitAvailable>0.0</ns2:LimitBenefitAvailable>
<ns2:LimitBenefitService>1</ns2:LimitBenefitService>
<ns2:LimitBenefitUsedService>0</ns2:LimitBenefitUsedService>
<ns2:LimitBenefitAvailableService>1</ns2:LimitBenefitAvailableService>
<ns2:QualifyingPeriodIndicator/>
<ns2:ClaimIndicator>B</ns2:ClaimIndicator>
<ns2:LimitPeriod>3</ns2:LimitPeriod>
<ns2:LimitPeriodType>R</ns2:LimitPeriodType>
<ns2:LimitScale>INDIV</ns2:LimitScale>
</ns2:LimitAndUsageDetails>
And I am interested in LimitCode, LimitType, LimitPeriod and LimitPeriodType elements.
I have tried the following assert script but it doesnt work.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( messageExchange.responseContent )
def pxml = new XmlSlurper().parseText(context.response)
def expected = [
"022":"N":"1":"C"
'023':'N':'3':'R',
'030':'N':'1':'C',
]
def xml = new XmlSlurper().parseText(context.response)
def actual = xml.'**'.findAll{it.name() == 'LimitAndUsageDetails'}.collectEntries{[(it.LimitCode.text()): it.LimitType.text(): it.LimitPeriod.text(): it.LimitPeriodType.text()]}
assert expected == actual
Here is what you need to do.
Expected data requires couple more items as opposed to previous question.
So need to create map(to identify which data to what element)
Since there are list of details to be verified, expected data should be list of maps.
Please see the Script Assertion below:
assert context.response, 'Response is empty or null'
//list of maps; each map for single usage detail
//If the details are more, you may use a csv data file; solution may vary slightly
def expected = [
[ LimitCode: '022', LimitType: 'N', LimitPeriod: 1, LimitPeriodType: 'C'],
[ LimitCode: '023', LimitType: 'N', LimitPeriod: 3, LimitPeriodType: 'R']
]
 
 
def xml = new XmlSlurper().parseText(context.respone)
//Build the actual list of map from response
def actual = xml.'**'.findAll{it.name() == 'LimitAndUsageDetails'}.collect{ [
LimitCode : it.LimitCode.text(),
LimitType : it.LimitType.text(),
LimitPeriod : it.LimitPeriod.text() as Integer,
LimitPeriodType : it.LimitPeriodType.text()
]
}.sort {it.LimitCode}
assert expected == actual
You may quickly try the same online demo
You could use the below code which is also to get Response node values in
def groovyutils=new com.eviware.soapui.support.GroovyUtils(context)
def holder=groovyutils.getXmlHolder(messageExchange.responseContent)
holder.namespaces["ns"]="http://www.webserviceX.NET/"
def conversionRate=holder.getNodeValue("//ns:ConversionRateResult")
i was not able to test on your code since i dont have the correct namespace, but this code works perfectly fine for getting a value from response of currency convertor
you just need to change xpath inside getNodeValue and the namespace URL. this way its simpler

How to assert array values in groovy using script assertion

I am writing a script assertion to see if a element value contains in the array list and if it does, it passes.
When I print the element:Number, I get like an example [1,2,3,3] as array. If Number contains say 3, script has to pass.
I have written below code which is failing, probably because the written value is an array list, how to assert an array value?
def response = messageExchange.getResponseContent()
def xml = new XmlSlurper().parseText(response)
def invoiceNumber= xml.'**'.findAll { it.name() == 'Number'}
log.info "$invoiceNumber"
assert invoiceNumber.contains(1)
The problem is that invoiceNumber is a Collection of groovy.util.slurpersupport.NodeChild elements instead of Integer elements. This is why the contains(3) comparison never returns true.
You've to convert array of groovy.util.slurpersupport.NodeChild to array of integers before the contains(), you can do it using the spread dot operator an NodeChild.toInteger(), so your script must be:
def response = messageExchange.getResponseContent()
def xml = new XmlSlurper().parseText(response)
def invoiceNumber= xml.'**'.findAll { it.name() == 'Number'}
log.info "$invoiceNumber"
// convert the array to array of integers
invoiceNumber = invoiceNumber*.toInteger()
// now you can perform the assert correctly
assert invoiceNumber .contains(3)
Hope it helps,

Determining an end node from file parsed with XmlParser

I have a method which needs to search an xml file which was parsed using XmlParser for an element by name and return it only if that element is an end node. For example:
class xmlTest extends GroovyTestCase {
def void test(){
def xmlBody = """
<rootElement>
<elementWithOneChild>
<endElement>Here is the end</endElement>
</elementWithOneChild>
<elementWithManyChildren>
<one>1</one>
<two>1</two>
<three>1</three>
</elementWithManyChildren>
</rootElement>"""
def parsedBody = new XmlParser().parseText(xmlBody)
def search1 = parsedBody.depthFirst().grep({it.name() == "elementWithOneChild"})
println search1[0].children().size()
def search2 = parsedBody.depthFirst().grep({it.name() == "endElement"})
println search2[0].children().size()
def search3 = parsedBody.depthFirst().grep({it.name() == "elementWithManyChildren"})
println search3[0].children().size()
}
}
My attempt to use Node.children().size() works except for the 1 to 1 case where an element contains one child element. In this case, search1.children().size() and search2.children().size() both return 1. Although, the size for elementWithManyChildren is 3. I am looking for some way to be able to tell an end node apart from an element with one child.
One way I have found to work is:
try{
search1[0].children().iterator().next().name()
}catch(e){
//If the next node does not have a name, it is an end node
}
But that solution just seems like a poor one.
might waste a couple of cycles but this should allow you to find terminal nodes
assert search1[0].'**'.size() == 2
assert search2[0].'**'.size() == 1
assert search3[0].'**'.size() == 4

Sorting arrays in Groovy

I'm trying to compare two arrays in groovy. My attempts so far have yielded a mixed response and therefore I'm turning to the collective for advice.
In the following code I'm taking 2 REST responses, parsing them and placing everything under the Invoice node into an array. I then further qualify my array so I have a list of InvoiceIDs and then try to compare the results of the two responses to ensure they are the same.
When I compare the array of InvoiceIDs (Guids) they match - this is not what I expect as the invoice order is currently different between my my 2 response sources.
When I sort the arrays of Invoices IDs the results differ.
I'm suspecting my code is faulty, but have spent an hour rattling through it, to no avail.
Any advice on sorting arrays in groovy or on the code below would be most appreciated:
gu = new com.eviware.soapui.support.GroovyUtils( context )
def xmlSlurper = new groovy.util.XmlSlurper()
// Setting up the response parameters
def responseSTAGE = xmlSlurper.parseText(context.expand('${GET Invoices - STAGE#Response}'));
def responseSTAGE2 = xmlSlurper.parseText(context.expand('${GET Invoices - STAGE2#Response}'));
responseInvoicesSTAGE = responseSTAGE.Invoices
responseInvoicesSTAGE2 = responseSTAGE2.Invoices
def arrayOfInvoicesSTAGE = []
def arrayOfInvoicesSTAGE2 = []
def counter = 0
for (invoice in responseInvoicesSTAGE.Invoice) {
arrayOfInvoicesSTAGE[counter] = responseInvoicesSTAGE.Invoice[counter].InvoiceID
//log.info counter+" STAGE"+arrayOfInvoicesSTAGE[counter]
arrayOfInvoicesSTAGE2[counter] = responseInvoicesSTAGE2.Invoice[counter].InvoiceID
//log.info counter+" STAGE2"+arrayOfInvoicesSTAGE2[counter]
counter++
}
log.info arrayOfInvoicesSTAGE
log.info arrayOfInvoicesSTAGE2
def sortedSTAGE = arrayOfInvoicesSTAGE.sort()
def sortedSTAGE2 = arrayOfInvoicesSTAGE2.sort()
log.info sortedSTAGE
As an aside, can't you replace:
def arrayOfInvoicesSTAGE = []
def arrayOfInvoicesSTAGE2 = []
def counter = 0
for (invoice in responseInvoicesSTAGE.Invoice) {
arrayOfInvoicesSTAGE[counter] = responseInvoicesSTAGE.Invoice[counter].InvoiceID
//log.info counter+" STAGE"+arrayOfInvoicesSTAGE[counter]
arrayOfInvoicesSTAGE2[counter] = responseInvoicesSTAGE2.Invoice[counter].InvoiceID
//log.info counter+" STAGE2"+arrayOfInvoicesSTAGE2[counter]
counter++
}
with
def arrayOfInvoicesSTAGE = responseInvoicesSTAGE.Invoice*.InvoiceID
def arrayOfInvoicesSTAGE2 = responseInvoicesSTAGE2.Invoice*.InvoiceID
Two arrays are considered equal in Groovy if they have they have the same number of elements and each element in the same position are equal. You can verify this by running the following code in the Groovy console
Integer[] foo = [1,2,3,4]
Integer[] bar = [4,3,2,1]
assert foo != bar
bar.sort()
assert foo == bar

Resources