Sorting arrays in Groovy - 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

Related

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

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()

Checking a value across multiple arrays

I have a context property named 'flights'. I want to check if there is no value for this property, then go to the 'Iteration' test step, else set the first value of the property as a test case property.
Now what I want to do is perform a compare using this test case property value with a couple of arrays. Below is the scenario;
Check if value is in the villas array, if so +1 to VillasCount, else check in hotels array, if in there then +1 to beachCount else +1 to noCount.
Code is below:
// define properties required for the script to run.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def dataFolder = groovyUtils.projectPath
//Define an empty array list to load data from datasheet
def dataTable_properties = [];
int villasCount = context.getProperty("villasCount")
def lines = new File(dataFolder + "/Test.csv").readLines()
def villas = []
lines.eachWithIndex { line, index ->
if (index) {
def data = line.split(',')*.trim()
if (data[0]) villas << data[0]
}
}
log.info "Villas : ${villas}"
context.setProperty("villasCount", villasCount)
Maybe something like:
for(f in flights){
if(villas.contains(f)){
villasCount = villasCount + 1
}
}
Not 100% sure what you needed to compare, but you could easily expand this to check whatever you wanted.
If this is way off please provide more information on what you were trying to compare.

Access variable value by its name as String (groovy)

I've done some research but I haven't found a working code for my case. I have two variables named test and test2 and I want to put them in a map in the format [test:valueof(test), test2:valueof(test2)]
My piece of code is the following:
def test="HELLO"
def test2="WORLD"
def queryText = "\$\$test\$\$ \$\$test2\$\$ this is my test"
def list = queryText.findAll(/\$\$(.*?)\$\$/)
def map = [:]
list.each{
it = it.replace("\$\$", "")
map.putAt(it, it)
}
queryText = queryText.replaceAll(/\$\$(.*?)\$\$/) { k -> map[k[1]] ?: k[0] }
System.out.println(map)
System.out.println(queryText)
Output:
Desired output:
"HELLO WORLD this is my test"
I think I need something like map.putAt(it, eval(it))
EDIT
This is the way I get my inputs. the code goes into the 'test' script
The ones on the right are the variable names inside the script, the left column are the values (that will later be dynamic)
You are almost there.
The solution is instead of putting the values into separate variables put them into the script binding.
Add this at the beginning ( remove the variables test and test2):
def test="HELLO"
def test2="WORLD"
binding.setProperty('test', test)
binding.setProperty('test2', test2)
and change this:
{ k -> map[k[1]] ?: k[0] }
to this:
{ k -> evaluate(k[1]) }
It should be very simple if you could use TemplateEngine.
def text = '$test $test2 this is my test'
def binding = [test:'HELLO', test2:'WORLD']
def engine = new groovy.text.SimpleTemplateEngine()
def template = engine.createTemplate(text).make(binding)
def result = 'HELLO WORLD this is my test'
assert result == template.toString()
You can test quickly online Demo
Final working code, thanks to all, in particular to dsharew who helped me a lot!
#input String queryText,test,test2,test3
def list = queryText.findAll(/\$\$(.*?)\$\$/)
def map = [:]
list.each{
it = it.replace("\$\$", "")
map.putAt(it, it)
}
queryText = queryText.replaceAll(/\$\$(.*?)\$\$/) { k -> evaluate(k[1]) }
return queryText

Retrieve value in map by key in Groovy

def text= '''<Rollback> <Kits>
<Kit ServerName='ust1twastool01a'>
<Backup>2016-10-18_20_34-46-_server-21.000.409_client-21.000.407.zip</Backup>
<Backup>2016-10-18_21_57-33-_server-21.000.409_client-21.000.407.zip</Backup>
<Backup>2016-10-19_02_40-03-_server-21.000.413_client-21.000.407.zip</Backup>
<Backup>2016-10-19_13_58-36-_server-21.000.413_client-21.000.407.zip</Backup>
<Backup>2016-10-20_03_14-34-_server-21.000.413_client-21.000.407.zip</Backup>
</Kit>
<Kit ServerName='another_server'>
<Backup>123123.zip</Backup>
<Backup>321321.zip</Backup>
</Kit>
</Kits></Rollback>'''
def xml = new XmlSlurper().parseText(text)
def map = [:]
i = 0
xml.Kits.Kit.each{node->
def list = []
node.Backup.each{kit->
list.add(kit)
}
map.put(node.#ServerName, list)
}
print map // print map with all keys and values
// Somehow, it's not working ...
print map['ust1twastool01a']
def map2 = ['1':["abc","123"], '2':["bcd", "456"]]
print map2['1']
​
I have been annoyed by the above code for almost the day. I don't understand why I can't get value by map['ust1twastool01a'].
I attached a screenshot from a console, it shows that map is not empty but just can't get its value by key. map2 is just control group as it has the similar structure to map string as key and list as value
Use as below:
map.put(node.#ServerName.text(), list)
On a side note, I believe you can simplify the code to just:
def xml = new XmlSlurper().parseText(text)
def map = xml.Kits.Kit.collectEntries { node ->
[ node.#ServerName.text(), node.Backup.collect() ]
}

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

Resources