问题
In my test case I have two test step that produce an XML response. The XML structure is slightly different from one another but the data is the same and ordered the same.
I have created a Groovy Script test step that will read the iterations of data from both XMLs and assert that they equal. The number of rows in these XML Response can exceed 500 rows.
The Test Case loops over 349 times.
When I run the test case, it lags on the groovy script assert for the first loop through - taking greater than 5 minutes to complete. I am trying to figure out a way to improve the current script or a better approach to comparing the two XML Response.
JDBC Response:
<Results>
<ResultSet fetchSize="128">
<Row rowNumber="1">
<id>1540107</id>
<name>10C/Ar1</name>
<code>10C/Ar1</code>
<subjectId>349176</subjectId>
</Row>
<Row rowNumber="2">
<id>1540108</id>
<name>11A/Ar1</name>
<code>11A/Ar1</code>
<subjectId>349177</subjectId>
</Row>
...
REST Response:
<Response>
<e>
<id>1540107</id>
<name>10C/Ar1</name>
<code>10C/Ar1</code>
<subjectId>349176</subjectId>
</e>
<e>
<id>1540108</id>
<name>11A/Ar1</name>
<code>11A/Ar1</code>
<subjectId>349177</subjectId>
</e>
...
Groovy Script:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
//API Response
def HolderA = groovyUtils.getXmlHolder(context.expand('${01_Test_Step_05#ResponseAsXml}'))
def CountA = HolderA.getNodeValues("//e").size();
log.info CountA
//Database Query Response
def HolderB = groovyUtils.getXmlHolder(context.expand('${01_Test_Step_04#ResponseAsXml#//Results[1]/ResultSet[1]}'))
def CountB = HolderB.getNodeValues("//Row").size();
log.info CountB
//Asser Response Sizes
assert CountA == CountB : 'Response Counts Dont Equal'
def i = 1
while(i < (CountA + 1)) {
//API Response Elements
def id_A = context.expand( '${01_Test_Step_05#ResponseAsXml#//e[' + i + ']/id}' )
def name_A = context.expand( '${01_Test_Step_05[GET]#ResponseAsXml#//e[' + i + ']/name}' )
def code_A = context.expand( '${01_Test_Step_05[GET]#ResponseAsXml#//e[' + i + ']/code}' )
def subjectId_A = context.expand( '${01_Test_Step_05[GET]#ResponseAsXml#//e[' + i + ']/subjectId}' )
//Database Query Response Elements
def id_B = context.expand( '${01_Test_Step_04#ResponseAsXml#//Results[1]/ResultSet[1]/Row[' + i + ']/id}' )
def name_B = context.expand( '${01_Test_Step_04#ResponseAsXml#//Results[1]/ResultSet[1]/Row[' + i + ']/name}' )
def code_B = context.expand( '${01_Test_Step_04#ResponseAsXml#//Results[1]/ResultSet[1]/Row[' + i + ']/code}' )
def subjectId_B = context.expand( '${01_Test_Step_04#ResponseAsXml#//Results[1]/ResultSet[1]/Row[' + i + ']/subjectId}' )
//Assert API Response Elements & Database Query Response Elements
assert id_A == id_B : 'Mismatching IDs'
assert name_A == name_B : 'Mismatching Names'
assert code_A == code_B : 'Mismatching Codes'
assert subjectId_A == subjectId_B : 'Mismatching Subject IDs'
i++
}
回答1:
There is an easy way to do it But this way will not highlight what did not matched between 2 XML. It will surely tell things did not matched
<ResultSet fetchSize="128">
<Row rowNumber="1">
<id>1540107</id>
<name>10C/Ar1</name>
<code>10C/Ar1</code>
<subjectId>349176</subjectId>
</Row>
<Row rowNumber="2">
<id>1540108</id>
<name>11A/Ar1</name>
<code>11A/Ar1</code>
<subjectId>349177</subjectId>
</Row>
</ResultSet>
</Results>
'''
def xml2='''<Response>
<e>
<id>1540107</id>
<name>10C/Ar1</name>
<code>10C/Ar1</code>
<subjectId>349176</subjectId>
</e>
<e>
<id>1540108</id>
<name>11A/Ar1</name>
<code>11A/Ar1</code>
<subjectId>349177</subjectId>
</e>
</Response>'''
def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def x1= groovyUtils.getXmlHolder(xml1)
def x2= groovyUtils.getXmlHolder(xml2)
def a1=x1.getNodeValues("//*:Row/*")
def a2=x2.getNodeValues("//*:e/*")
if(a1.toString()==a2.toString())
{
log.info "Values matched in both XML for values"
}
else
{
log.error "Values did not matched in both XML for values"
}
Though this one is hard to debug as to where is the failure but an efficient way of comparing all values across XML. You can even compare at various nodes level.
This one is even easier to understand compared to XMLParser
回答2:
I believe that your many context.expand is the expensive part.
I would use XmlSlurper, and then simply loop over the rows.
I assume the rows are ordered in the same manner.
You will need to adjust line 3 and 4 to suit your needs, to fetch the XML correctly. For testing purposes, I just added two small Groovy Scripts, which returned the XML I needed for the testing.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def request1 = testRunner.testCase.getTestStepByName("Xml1").getPropertyValue("result")
def request2 = testRunner.testCase.getTestStepByName("Xml2").getPropertyValue("result")
def slurper = new XmlSlurper()
def req1 = slurper.parseText(request1)
def req2 = slurper.parseText(request2)
def size1 = req1.ResultSet.Row.size()
def size2 = req2.e.Row.size()
assert size1 == size2 : 'Response Counts Dont Equal'
for (def x=0 ; x<size1 ; x++) {
assert req1.ResultSet.Row[x].id == req2.e.Row[x].id : 'Mismatching IDs in row ' + x + " values " + req1.ResultSet.Row[x].id + " / " + req2.e.Row[x].id
assert req1.ResultSet.Row[x].name == req2.e.Row[x].name : 'Mismatching Names in row ' + x + " values " + req1.ResultSet.Row[x].name + " / " + req2.e.Row[x].name
assert req1.ResultSet.Row[x].code == req2.e.Row[x].code : 'Mismatching Codes in row ' + x + " values " + req1.ResultSet.Row[x].code + " / " + req2.e.Row[x].code
assert req1.ResultSet.Row[x].subjectId == req2.e.Row[x].subjectId : 'Mismatching SubjectIds in row ' + x + " values " + req1.ResultSet.Row[x].subjectId + " / " + req2.e.Row[x].subjectId
}
来源:https://stackoverflow.com/questions/54308611/soapui-comparing-two-xml-responses-is-incredibly-slow