Introduction
Since soapUI allows users to add Groovy scripts in large number of places ( property expansions, setup /teardown scripts, listeners, test step, etc… ) users can use any technology to reach to the goal. Lets look at those which can make our life easier when it comes to XML parsing.
soapUI XML Support
Old way would be soapUI way or using GroovyUtils from soapUI. Its goal is to simplify scripting and it can be instantiate from any Groovy script in soapUI, with:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
where context is available in any Groovy script in soapUI. Lets look at GroovyUtils:
GroovyUtils Methods | |
---|---|
expand(property) |
returns value of property, if there are property expansions they are expanded. |
extractErrorLineNumber(error) |
returns line number where error occurred |
getProjectPath()
|
returns path to project file |
getXml(node)
|
returns xml as a string from passed node |
getXmlHolder(xmlPropertyOrString) |
returns XmlHolder as a result of parsing passed Xml string |
registerJdbcDriver(driver) |
register JDBC driver for use in Groovy script |
setPropertyValue(testStep, property, value) |
sets a value for given test step property |
This time getXmlHolder is one that does what we need. Pars a given string as XML and returns object which we can use to manipulate with it.
XmlHolder Methods | |
---|---|
declareNamespace(prefix, uri) |
declare namespace prefix and URI |
getDomNode(xpath) |
returns a DOM node pointed by XPath expression |
getDomNodes(xpath) |
returns an array of DOM nodes pointed by XPath expression |
getNamespaces() |
returns a Map of namespaces |
getNodeValue(xpath) |
returns a value of node specified by XPath expression |
getNodeValues(xpath) |
returns an array of values specified by XPath expression |
getPrettyXml() |
returns a formatted XML |
getXml() |
returns a XML |
getXmlObject() |
returns a XmlBean Object |
removeDomNodes(xpath) | removes a nodes specified by XPath expression |
setNodeValue(xpath, value) |
set a node value |
updateProperty() |
if a XmlHolder is created from test step property this updates that property |
updateProperty(prettyPrint) |
if a XmlHolder is created from test step property this updates that property with well formatted XML |
Few Examples
Assume you have response:
<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:sim=”http://www.example.org/SimpleSocialSOA/”>
<soapenv:Header/>
<soapenv:Body>
<sim:LoginResponse>
<id>4456643453</id>
</sim:LoginResponse>
</soapenv:Body>
</soapenv:Envelope>
For this examples I added a Properties Test Step with property response.
1. Parsing XML
According to that to get id from response you can do:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
log.info holder.getNodeValue(“//id”)
log.info holder[‘//id’]
notice two ways to get node value with getNodeValue method and with [] operator. Difference is that getNodeValue will return first value that can be found with set XPath, while [] operator returns a array of values.
If you assume that response is like:
<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:sim=”http://www.example.org/SimpleSocialSOA/”>
<soapenv:Header/>
<soapenv:Body>
<sim:LoginResponse>
<id>4456643453</id>
<id>4456643452</id>
<id>4456643451</id>
<id>4456643450</id>
</sim:LoginResponse>
</soapenv:Body>
</soapenv:Envelope>
Than this script:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
log.info holder.getNodeValue(“//id”)
for( node in holder[‘//id’] )
log.info node
will produce result like this:
2. Updating XML
Response as above and we do:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
holder.setNodeValue(“//id”, “aaaaa”)
for( node in holder[‘//id’] )
log.info node
def holder2 = groovyUtils.getXmlHolder(“Properties#response”)
holder2.getNodeValue(“//id”)
for( node in holder2[‘//id’] )
log.info node
Result is:
from this we can learn:
- if there are several nodes as result of XPath expression only first’s node value will be changed with setNodeValue
- setting node value is not enough to update property value, we forgot to useupdateProperty method
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
holder.setNodeValue(“//id”, “aaaaa”)
for( node in holder[‘//id’] )
log.info node
holder.updateProperty()
def holder2 = groovyUtils.getXmlHolder(“Properties#response”)
holder2.getNodeValue(“//id”)
for( node in holder2[‘//id’] )
log.info node
Instead of using:
holder.setNodeValue(“//id”, “aaaaa”)
you can use also:
holder[“//id”] = “aaaaa”
And if XmlNode is created from property as in example above useupdateProperty method to apply your changes to property or useGroovyUtils.setPropertyValue method.
Groovy XML
There are three classes built in Groovy for processing XML: XMLParser, XMLSlurperand DOMCategory. Best practice is to use XMLSlurper in soapUI. Reason is that it have smallest memory footprint from all three. I would no go in depths for those, you can read here XML processing.
This for example:
import groovy.xml.StreamingMarkupBuilder
def response = context.testCase.testSteps[‘Properties’].properties[‘response’].value
def responseXml = new XmlSlurper().parseText(response)
responseXml.breadthFirst().each {
def v = it.toString()
if ( it.name() == ‘id’)
it.replaceBody(“$v XX”)
}
appends ” XX” to values of all id nodes.
JSON Slurper
JSON is soapUI
Nice and peachy but…
- Names can contain letters, numbers, and other characters
- Names cannot start with a number or punctuation character
- Names cannot start with the letters xml (or XML, or Xml, etc)
- Names cannot contain spaces
{
“trends”: {
“2012-08-29 08:20”: [
{
“events”: null,
“name”: “Bizim İçin Saldır Fenerbahçe”,
“query”: “\”Bizim İçin Saldır Fenerbahçe\””,
“promoted_content”: null
},
{
“events”: null,
“name”: “#RemajaIndonesiaSeptemberWish”,
“query”: “#RemajaIndonesiaSeptemberWish”,
“promoted_content”: null
},
{
“events”: null,
“name”: “Most Share-Worthy Video”,
“query”: “\”Most Share-Worthy Video\””,
“promoted_content”: null
Asserting JSON
import groovy.json.JsonSlurper
def response = messageExchange.response.responseContent
def slurper = new JsonSlurper()
def json = slurper.parseText response
assert json.trends.’2012-08-29 08:20′ != null
Notice that I had to put date under quotes since date contains white space, buttrends are good. And now I want to be sure that I have eight trends for that date and time:
assert json.trends.’2012-08-29 08:20′.size == 8
and 7th element name is Toby:
assert json.trends.’2012-08-29 08:20′[7].name == “Toby”
and so on…Whole script can look like this:
import groovy.json.JsonSlurper
def response = messageExchange.response.responseContent
def slurper = new JsonSlurper()
def json = slurper.parseText response
assert json.trends.’2012-08-29 08:20′ != null
assert json.trends.’2012-08-29 08:20′.size == 8
assert json.trends.’2012-08-29 08:20′[7].name == “Toby”
this may help also
http://lgsofttest.blogspot.no/2013/10/how-to-add-or-deletecomment-xml-node-or.html