SoapUI 比较两个 XML 响应非常慢
SoapUI Comparing two XML responses is incredibly slow
在我的测试用例中,我有两个测试步骤会产生 XML 响应。 XML 结构彼此略有不同,但数据相同且顺序相同。
我创建了一个 Groovy 脚本测试步骤,它将从两个 XML 中读取数据迭代并断言它们相等。这些 XML 响应中的行数可以超过 500 行。
测试用例循环超过 349 次。
当我 运行 测试用例时,它在第一个循环中滞后于 groovy 脚本断言 - 需要超过 5 分钟才能完成。我正在尝试找出一种改进当前脚本的方法或一种更好的方法来比较两个 XML Response.
JDBC 响应:
<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>
<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 脚本:
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++
}
我相信你的很多context.expand是贵的部分。
我会使用 XmlSlurper,然后简单地遍历行。
我假设行的排序方式相同。
您需要调整第 3 行和第 4 行以满足您的需要,以正确获取 XML。出于测试目的,我刚刚添加了两个小的 Groovy 脚本,它们返回了测试所需的 XML。
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
}
有一个简单的方法可以做到,但是这种方法不会突出显示2 XML 之间不匹配的内容。它肯定会告诉不匹配的东西
<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"
}
虽然这个很难调试到哪里出了问题,但这是一种比较 XML 中所有值的有效方法。您甚至可以在各个节点级别进行比较。
这个比 XMLParser 更容易理解
在我的测试用例中,我有两个测试步骤会产生 XML 响应。 XML 结构彼此略有不同,但数据相同且顺序相同。
我创建了一个 Groovy 脚本测试步骤,它将从两个 XML 中读取数据迭代并断言它们相等。这些 XML 响应中的行数可以超过 500 行。
测试用例循环超过 349 次。
当我 运行 测试用例时,它在第一个循环中滞后于 groovy 脚本断言 - 需要超过 5 分钟才能完成。我正在尝试找出一种改进当前脚本的方法或一种更好的方法来比较两个 XML Response.
JDBC 响应:
<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>
<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 脚本:
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++
}
我相信你的很多context.expand是贵的部分。
我会使用 XmlSlurper,然后简单地遍历行。
我假设行的排序方式相同。
您需要调整第 3 行和第 4 行以满足您的需要,以正确获取 XML。出于测试目的,我刚刚添加了两个小的 Groovy 脚本,它们返回了测试所需的 XML。
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
}
有一个简单的方法可以做到,但是这种方法不会突出显示2 XML 之间不匹配的内容。它肯定会告诉不匹配的东西
<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"
}
虽然这个很难调试到哪里出了问题,但这是一种比较 XML 中所有值的有效方法。您甚至可以在各个节点级别进行比较。
这个比 XMLParser 更容易理解