What is the right way to compare two strings in SoapUI with groovy script assertion? - groovy

I need to compare two strings in SoapUI. The first one is from a text file stored in my local directory, and the second one is from an XML response I get from a REST API operation. Before comparing the two strings, I use some methods on them to remove the header because they contain information like Dates and Processing Time which is sure to be different each time.
Below is what I've tried.
def xml = messageExchange.responseContentAsXml
String fileData = new File("C://Users/362784/project/outputPGB123.txt").text
String responseContent = new XmlSlurper().parseText(xml)
String fileDataFiltered = fileData.substring(fileData.indexOf("PASSED :"))
String responseContentFiltered = responseContent.substring(responseContent.indexOf("PASSED :"))
log.info(fileDataFiltered)
log.info(responseContentFiltered)
assert fileDataFiltered == responseContentFiltered
Here is the error I received
SoapUI error message
and my two identical log.info
log.info
Here's what the XML response looks like
I am new to SoapUI and I'm not sure what those two are actually comparing but I've checked the log.info of them on https://www.diffchecker.com/diff and the contents are identical. However, this assertion returns an error.
Can anyone point out what I did wrong and how do I get the result as passed?

In Java/Groovy you compare string values for equality like this:
assert fileDataFiltered.equals(responseContentFiltered)
See if that solves your problem.
The == comparator could, for example, compare object instances which could fail even if the text values are identical. See here for a more in-depth explanation.
EDIT:
Having seen your sample, it looks like the value you are comparing is inside XML character data (CDATA).
Consider the following example from here:
Some XML:
def response = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sam="http://www.example.org/sample/">
<soapenv:Header/>
<soapenv:Body>
<sam:searchResponse>
<sam:searchResponse>
<item><id>1234</id><description><![CDATA[<item><width>123</width><height>345</height><length>098</length><isle>A34</isle></item>]]></description><price>123</price>
</item>
</sam:searchResponse>
</sam:searchResponse>
</soapenv:Body>
</soapenv:Envelope>
'''
Then access the CDATA node with XmlSlurper:
def Envelope = new XmlSlurper().parseText(response)
def cdata = Envelope.Body.searchResponse.searchResponse.item.description
log.info cdata
log.info cdata.getClass()
assert cdata instanceof groovy.util.slurpersupport.NodeChildren
As you can see, the value returned is of object NodeChildren. You can convert it to a string with:
log.info cdata.toString()
log.info cdata.toString().getClass()
So let's do a comparison (as per cfrick's comment, you can use == or .equals())
def expectedCdata = '<item><width>123</width><height>345</height>length>098</length><isle>A34</isle></item>'
if (cdata.toString().equals(expectedCdata)) { log.info 'Equal' }
else {log.info 'Different'}
It still fails ???
Well, that is because of a residual newline that isn't obvious from printing with log.info, if you remove whitespace it works in this case:
if (cdata.toString().replaceAll("\\s","").equals(expectedCdata)) { log.info 'Equal' }
else {log.info 'Different'}
As you can see, there are many levels of possible failure. You have to work through it.

Related

Transfer list between Groovy test steps (SoapUI)

I have one test case which is called (started and finished) before every run of other test cases. It is something like 'test data preparation' test case. Output from this test case is list with some elements, list looks like this:
def list = ['Login', 'Get Messages', 'Logout', etc.]
List is different on every run. I need to transfer this list from 'test data preparation' test case to other test cases. Transfer will be between two Groovy scripts.
How to transfer list between two Groovy test steps in SoapUI?
As I understand it:
You have one TestCase, which you call from every other TestCase.
I assume this is done using a "Run TestCase" teststep?
You would like to be able to pass a list of strings
As I read it, parameters go one way. From the "external testcase" and back to the calling testcase. There is no "input" from each testcase to this "external testcase"?
The Groovy Script in your "external testcase" may then generate a String result, which in turn can be converted to something like an Array or ArrayList of Strings.
This could be a string with values separated by ;
def result = ""
result += "Entry1;"
result += "Entry2;"
result += "Entry3;"
// You may want to add a line of code that removes the last ;
return result
This result will then be easily retrieved from Groovy Scripts elsewhere, by adding a few lines of code.
If the Groovy Script is placed in another TestCase, but in the same TestSuite, you may retrieve the result using:
def input = testRunner.testCase.testSuite.getTestCaseByName("Name of TestCase").getTestStepByName("Groovy Script Name").getPropertyValue("result")
If it is placed in a TestCase in a different TestSuite, you may use:
def input = testRunner.testCase.testSuite.project.getTestSuiteByName("Test Suite Name").getTestCaseByName("Test Case Name").getTestStepByName("Groovy Script Name").getPropertyValue("result")
and then loop over the input doing something like:
for (def s : input.split(";")) {
log.info s
// Do your stuff here
}
I hope that makes sense...? :)
from groovy step 1 you shall return the list:
def list = ['Login', 'Get Messages', 'Logout']
return list
from groovy step 2 you can get this returned list
def result = context.expand( '${Groovy Script 1#result}' )
list = result.tokenize('[,] ')
list.each{
log.info it
}
note that you get a string that you have to convert back to a list (tokenize).
I did this with SOAPUI pro.
Another way (ugly) would be to store the list in a custom property in groovy script 1 (using testRunner.testCase.setPropertyValue("myList",list.toString())
and to recover it in groovy step 2 (testRunner.testCase.getPropertyValue("myList")
I hope that will help
EDIT : if list elements contain spaces
this is not very clean and I hope someone will help to provide something better but you can do the following :
list = "['Login - v1', 'Get Messages - v2', 'Logout - v1']"
list = list.replace('\'','\"')
def jsonSlurper = new groovy.json.JsonSlurper()
list = jsonSlurper.parseText(list)
list.each{
log.info it
}
Alex

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.

Assert multiple values in an XML response received on querying DB in SOAP UI

I am trying to retrieve some data from db and based on the response, I have to pass or fail a test case. I have to do this each time I query the db
I am able to make the connection to the db and get the response. However, not quite sure on how to assert the values from the response
Tried to use Script Assertion but not able to figure out as I am completely new at this
<Results>
<ResultSet fetchSize="10">
<Row rowNumber="1">
<T1>TEXT1</T1>
<T2>TASK1</T2>
<T3>Value1</T3>
<T4>xyz</T4>
</Row>
<Row rowNumber="2">
<T1>TEXT2</T1>
<T2>TASK2</T2>
<T3>Value1</T3>
<T4>ABC</T4>
</Row>
</ResultSet>
From the above response, on the first step I will have to assert that "TASK1" exists and the "Value1" exists with in the same set followed by the "TASK2" and "Value1"
Please let me know if this is vague so that I can try to modify my query
Use Xpath assertion instead
Assertion 1
/Results/ResultSet[#fetchSize="10"]/Row[1]/T1
Expected result
Task1
Assertion 2
/Results/ResultSet[#fetchSize="10"]/Row[1]/T3
Expected result
Value1
You can add as many Xpath Assertion as you want for any number of nodes.
Quick Tip: To generate XPaths use online tools or Oxygen XML Editor. :)
You can use Script Assertion for the JDBC Request test step in soapUI.
Script assertion
//define your expected data as map. You may add more key value pairs if more Rows
def expectedData = ['TASK1':'Value1', 'TASK2':'Value1']
//Assert if the response is not null
assert context.response, 'Response is not null or empty'
//Parse and get rows
def rows = new XmlSlurper().parseText(context.esponse).ResultSet.Row
def getRowData = { data, elementName, elementValue ->
data.'**'.findAll { it.name() == elementName && it == elementValue }*.parent()
}
def assertionErrors = new StringBuffer()
//Loop thur expectedData and capture the errors
expectedData.each { key, value->
def matchingRow = getRowData(rows, 'T2', key)[0]
value == matchingRow.T3.text() ?: assertionErrors.append("Assertion failed for rowNumber ${matchingRow.#rowNumber}\n")
}
//Check and show the result
if (assertionErrors) {
throw new Error(assertionErrors.toString())
} else {
log.info 'Assertions passed'
}
You may quickly try the solution online Demo; it shows how failure error message look like.
Note that, column names T2, T3are used in above script. If the names are different in original result, just make the change at your end.
Also note that assertion is not used deliberately to catch all the comparison issues, do not want to stop at first compare issue.
Try XmlSlurper: http://groovy-lang.org/processing-xml.html
To check TASK1:
def results = new XmlSlurper().parseText(response)
def row1 = results.ResultSet.find { node->
node.name() == 'Row' && node.#rowNumber == '1'
}
assert row1.T2 == 'TASK1'
I hope you'll be able to do the rest by your own ;)

SoapUI, temper request data break when value is read from property file

I have a groovy script as the first test step inside a test case, part of it looks like:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("SampleTestt#Request").getXml()
log.info holder
When SampleTest test step has all element values hardcoded, the request xml can be printed fine.
However if some of the request values is read from a test case property, like the following for example
${#TestCase#Id}
The the above groovy script through error as:
org.apache.xmlbeans.XMLException: error: Unexpected character encountered : '$'
Can you please help?
Thanks.
You can use context.expand() to evaluate the properties inside your request and then parse the result to xmlHolder, your code could looks like:
// get your request replacing the properties inside by their values
def xmlRequest = context.expand('${SampleTestt#Request}')
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder(xmlRequest)
log.info holder.getXml()
Note that I use SampleTestt as your test step request name, but I think that the last t could be a typo... check if it's the correct request name before use the code.
Hope this helps,

Find an element in XML using XML Slurper

"I have a code that is working as expected but now I have to find the element in different format. Example is below
<car-load>
<car-model model="i10">
<model-year>
<year.make>
<name>corolla</name>
</year.make>
</model-year>
</car-model>
</car-load>
I have to find the value of "corolla" from this XML. Please reply.
You can run this in the Groovy console
def text = '''
<car-load>
<car-model model="i10">
<model-year>
<year.make>
<name>corolla</name>
</year.make>
</model-year>
</car-model>
</car-load>'''
def records = new XmlSlurper().parseText(text)
// a quick and dirty solution
assert 'corolla' == records.toString()
// a more verbose, but more robust solution that specifies the complete path
// to the node of interest
assert 'corolla' == records.'car-model'.'model-year'.'year.make'.name.text()

Resources