Groovy脚本断言,用于验证XML对脚本中CSV文件中的值的响应中的属性

时间:2014-05-28 18:07:50

标签: xml csv groovy soapui

我目前正在使用SoapUI根据我在另一个脚本(Located here for those interested)中从我的CSV文件中提取的值来调用Web服务。我要做的是解析该webservice调用的响应,以验证每个Subscriber元素的externalId值是否与CSV文件中的值匹配(通过以下方式保存在测试用例属性中)其他脚本),并且没有任何额外/更少的返回。

肥皂反应的一个例子见下文。

<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>

我想要解决的问题是:

  • 计算响应中的订阅者元素数。与csv / testcase属性中的非空值数量进行比较。如果不相等,立即失败。
  • 对于每个externalId属性,与csv / testcase属性中的所有非空值进行比较,如果匹配,则将计数器(props / csv中的非空值数)减1。如果在所有比较结束时计数器不等于零,则失败。否则脚本断言就会通过。

不幸的是,我对Groovy和SoapUI非常陌生,而且我不确定如何真正实现这一点,所以如果有任何想法或提示,我们将不胜感激!

1 个答案:

答案 0 :(得分:2)

我建议另一种选择:

  1. 将Web服务中的所有Subscriber externalId属性读入字符串列表并对列表进行排序。
  2. 将所有CSV值读入字符串列表并对列表进行排序。
  3. 断言两个列表是相同的。
  4. 您可以使用此示例作为基础。你还要做的是:

    1. 使用网络服务URI将XmlSlurper.parseText()替换为XmlSlurper.parse()
    2. 我认为将static externalId列表保存为CSV文件没有任何价值。相反,我使用了一个简单的文件,其中每行包含一个externalId(没有逗号分隔)。使用CSV应该相当容易。
    3. XML as String:

      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>"
      

      检索订户节点列表:

      def subscribers = new XmlSlurper(false, true).parseText(xml).Body.searchResponse.result.Subscriber
      // Replace parseText with parse(uri)
      

      将XML Subscriber元素转换为String:

      列表

      def idsFromSoap = subscribers.collect{it.@externalId.text()}.sort()

      collect()方法通过it.@externalId.text()将订阅者节点转换为(externalId属性)字符串列表。然后对转换后的String列表进行排序。

      现在,创建一个包含以下内容的文件:

      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
      

      我故意扰乱了这些ids。我称之为ids.csv,即使它当然不是CSV文件。

      将文件行读入(隐含)String列表并排序:

      def idsFromFiles = new File("ids.csv").readLines()*.trim().sort()

      *是扩展运算符,意味着使用readLines()读取的列表中的每个项都被修剪(如果文件行没有空格,则没有修剪)。

      最后,比较两个列表以验证它们包含相同的项目:

      assert idsFromSoap == idsFromFiles

      修改

      关于你的意见: 是。只要响应是有效的XML / XHTML,parse(String)就会接受有效的URL,例如ws.web.blah.com并解析响应。因此,您可以完全跳过使用SOAP UI,只需调用URL。

        

      如何在不处理上下文变量的情况下获得整个响应?

      它根本与SOAP UI上下文无关。

      对于SOAP UI,我不熟悉API。但只要您可以将响应保存到String(或文件/流并使用重载的parse()方法),代码就可以工作。