[英]Groovy script assertion to verify attributes in XML response to values in CSV file in script
I'm currently using SoapUI to make a call to a webservice based on a value I've pulled from my CSV file in another script ( Located here for those interested ). 我目前正在使用SoapUI根据从另一个脚本中的CSV文件中提取的值来调用Web服务( 位于此处,供那些感兴趣的人使用 )。 What I'd like to do is parse the response of that webservice call to verify that the
externalId
values for every Subscriber element match the ones in the CSV file (which are are saved in the test case properties via the other script), and that there aren't any extra/less being returned. 我想做的是解析该webservice调用的响应,以验证每个Subscriber元素的
externalId
值是否与CSV文件中的externalId
值匹配(该值通过其他脚本保存在测试用例属性中),并且没有任何额外/更少的退货。
An example of the soap response is seen below. 肥皂响应的示例如下。
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<ws:searchResponse xmlns:ws="http://ws.web.blah.com">
<result dataUpdated="false">
<Subscriber lastReportDate="2014-05-28T11:00:02-03:00" externalId="20107A-R29O12KH11113233" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="803227" macAddress="D2:9F:EE:11:32:33" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.33" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132333" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101553" macAddress="AB:CD:11:13:23:33" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.32" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132332" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101550" macAddress="AB:CD:11:13:23:32" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.31" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132331" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101545" macAddress="AB:CD:11:13:23:31" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.23" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132323" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101542" macAddress="AB:CD:11:13:23:23" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.22" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132322" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101537" macAddress="AB:CD:11:13:23:22" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber ip="11.13.23.21" lastReportDate="2014-05-28T12:07:16.998-03:00" externalId="12345678-1234-ABCD-ABCD-ABCD11132321" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="101533" macAddress="AB:CD:11:13:23:21" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber externalId="32321070" neighborhoodID="103290" neighborhood="PMBKXXDSL11" city="TORO" nodeId="100942" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber externalId="PMBKONOLT11:3-2-3-2-1070" neighborhoodID="103290" neighborhood="PMBKXXDSL11" city="TORO" nodeId="100941" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber lastReportDate="2014-05-28T12:00:01-03:00" externalId="001404-D29247113233" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="100716" macAddress="D2:9D:CC:11:32:33" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
<Subscriber lastReportDate="2014-05-28T12:00:01-03:00" externalId="001A73-WECO10KH11113233" classification="noerror" neighborhoodID="103280" neighborhood="PMBKONOLT11" city="TORO" nodeId="100414" macAddress="D2:9A:BB:11:32:33" lastName="first2047 last2047" phoneNumber="5068880029" subscriberId="100107"/>
</result>
</ws:searchResponse>
</env:Body>
</env:Envelope>
What I was thinking for a solution would be something along the lines of: 我在想一种解决方案的思路是:
externalId
attribute, compare with all non-null values in csv/testcase properties, if there's a match, decrease a counter(number of non-nulls in props/csv) by one. externalId
属性,将其与csv / testcase属性中的所有非空值进行比较(如果存在匹配项),请将计数器(props / csv中的非空数)减少1。 If by the end of all the compares the counter doesn't equal zero, then fail. Unfortunately I'm very new to Groovy and SoapUI, and I'm unsure of how to really implement this, so if anyone has any ideas or tips it would be greatly appreciated! 不幸的是,我对Groovy和SoapUI还是陌生的,我不确定如何真正实现这一点,因此,如果有人有任何想法或技巧,将不胜感激!
I suggest another alternative: 我建议另一种选择:
You can use this example as a basis. 您可以使用此示例作为基础。 What you are left to do is:
您要做的是:
XmlSlurper.parseText()
with XmlSlurper.parse()
using the Web Service URI. XmlSlurper.parseText()
与XmlSlurper.parse()
使用Web服务的URI。 The XML as String: XML作为字符串:
def xml = "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
" <env:Header/>\n" +
" <env:Body>\n" +
" <ws:searchResponse xmlns:ws=\"http://ws.web.blah.com\">\n" +
" <result dataUpdated=\"false\">\n" +
" <Subscriber lastReportDate=\"2014-05-28T11:00:02-03:00\" externalId=\"20107A-R29O12KH11113233\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"803227\" macAddress=\"D2:9F:EE:11:32:33\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.33\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132333\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101553\" macAddress=\"AB:CD:11:13:23:33\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.32\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132332\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101550\" macAddress=\"AB:CD:11:13:23:32\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.31\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132331\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101545\" macAddress=\"AB:CD:11:13:23:31\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.23\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132323\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101542\" macAddress=\"AB:CD:11:13:23:23\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.22\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132322\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101537\" macAddress=\"AB:CD:11:13:23:22\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber ip=\"11.13.23.21\" lastReportDate=\"2014-05-28T12:07:16.998-03:00\" externalId=\"12345678-1234-ABCD-ABCD-ABCD11132321\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"101533\" macAddress=\"AB:CD:11:13:23:21\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber externalId=\"32321070\" neighborhoodID=\"103290\" neighborhood=\"PMBKXXDSL11\" city=\"TORO\" nodeId=\"100942\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber externalId=\"PMBKONOLT11:3-2-3-2-1070\" neighborhoodID=\"103290\" neighborhood=\"PMBKXXDSL11\" city=\"TORO\" nodeId=\"100941\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber lastReportDate=\"2014-05-28T12:00:01-03:00\" externalId=\"001404-D29247113233\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"100716\" macAddress=\"D2:9D:CC:11:32:33\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" <Subscriber lastReportDate=\"2014-05-28T12:00:01-03:00\" externalId=\"001A73-WECO10KH11113233\" classification=\"noerror\" neighborhoodID=\"103280\" neighborhood=\"PMBKONOLT11\" city=\"TORO\" nodeId=\"100414\" macAddress=\"D2:9A:BB:11:32:33\" lastName=\"first2047 last2047\" phoneNumber=\"5068880029\" subscriberId=\"100107\"/>\n" +
" </result>\n" +
" </ws:searchResponse>\n" +
" </env:Body>\n" +
"</env:Envelope>"
Retrieve the subscribers node list: 检索订户节点列表:
def subscribers = new XmlSlurper(false, true).parseText(xml).Body.searchResponse.result.Subscriber
// Replace parseText with parse(uri)
Transform the XML Subscriber elements into a list of String: 将XML Subscriber元素转换为String列表:
def idsFromSoap = subscribers.collect{it.@externalId.text()}.sort()
The collect()
method transforms Subscriber nodes into a list of (externalId attribute ) String via it.@externalId.text()
. collect()
方法通过it.@externalId.text()
将订户节点转换为(externalId属性)String的列表。 The transformed String list is then sorted. 然后对转换后的字符串列表进行排序。
Now, create a file with the following content: 现在,创建一个具有以下内容的文件:
12345678-1234-ABCD-ABCD-ABCD11132321
001404-D29247113233
001A73-WECO10KH11113233
12345678-1234-ABCD-ABCD-ABCD11132322
PMBKONOLT11:3-2-3-2-1070
12345678-1234-ABCD-ABCD-ABCD11132323
32321070
12345678-1234-ABCD-ABCD-ABCD11132333
20107A-R29O12KH11113233
12345678-1234-ABCD-ABCD-ABCD11132331
12345678-1234-ABCD-ABCD-ABCD11132332
I've scrambled the ids on purpose. 我故意加扰了ID。 I've called it
ids.csv
even though it's not a CSV file of course. 我称它为
ids.csv
,尽管它当然不是CSV文件。
Read the file lines into (implicit) list of String and sort: 将文件行读入(隐式)String列表中并进行排序:
def idsFromFiles = new File("ids.csv").readLines()*.trim().sort()
*
is the spread operator meaning every item in the list read using readLines()
is trimmed (you don't have trim if the file lines are kept with no spaces). *
是传播运算符,表示使用readLines()
读取的列表中的每个项目都会被修剪(如果文件行没有空格,则不会修剪)。
Finally, compare the two lists to verify they contain the same items: 最后,比较两个列表以确认它们包含相同的项目:
assert idsFromSoap == idsFromFiles
EDIT 编辑
As to your comments: Yes. 关于您的评论:是的。
parse(String)
accepts a valid URL such as ws.web.blah.com and parses the response, as long as the response is a valid XML/XHTML. parse(String)
接受有效的URL(例如ws.web.blah.com)并解析响应,只要响应是有效的XML / XHTML。 So you can skip using SOAP UI altogether, and just invoke the URL. 因此,您可以完全跳过使用SOAP UI的过程,而仅调用URL。
how does that get the entire response without dealing with the context variable?
如何在不处理上下文变量的情况下获得整个响应?
It has nothing to do with SOAP UI context at all. 它与SOAP UI上下文完全无关。
As for SOAP UI, I'm not familiar with the API. 至于SOAP UI,我对API并不熟悉。 But as long as you can save the response to a String (or File/Stream and use the overloaded
parse()
methods), the code should work. 但是只要您可以将响应保存到String(或File / Stream并使用重载的
parse()
方法),代码就应该可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.