Forum Discussion

amit_db's avatar
amit_db
New Contributor
9 years ago

Not able to add xpath assertion on a complex REST API response

Hi,

 

 

I am using SoapUI 5.2.1 (free version). I am testing a REST API and trying to add assertion to the response message I am getting. Problem is that the response I am getting is not simple, the XML is wrapped in CDATA, see below for the an excerpt from the response message:


<html>
   <head>
      <link href="/ddd/ddddd.css" media="screen" rel="stylesheet"/>
   </head>
   <body>
      <table id="temporalObjects">
         <caption>Data</caption>
         <tr>
            <th>DOCUMENT</th>
            <th>xxxxxx</th>
            <th>ffffff</th>
            <th>dsfdfdfd</th>
            <th>dfdfdf</th>
            <th>fdfdfd</th>
            <th>dsdsdsds</th>
            <th>vcxvdvd</th>
            <th>gssfsfs</th>
            <th>geegegge</th>
            <th>ewewewew</th>
         </tr>
         <tr>
            <td>
               <pre><![CDATA[<?xml version="1.0" encoding="UTF-8"?><xxxWrapper:yyyMMessage xmlns:xxxWrapper="xxxWrapper" .....>
    <MessageId>.....</MessageId>
    <MessageType>xxxx</MessageType>
    <MessageSender>jjjj</MessageSender>
    <MessageSendingDateTime>2016-09-20T10:02:51.869</MessageSendingDateTime>
    <MessageSchemaVersion>1.0.0</MessageSchemaVersion>
    <Event>
        <EventId>2</EventId>
        <EventType>Changed Entity</EventType>
        <Object>
            <ObjectId>....</ObjectId>
            <ObjectVersionNumber>1.0.0</ObjectVersionNumber>
            <ObjectType>.....</ObjectType>
            <ObjectOwner>...</ObjectOwner>
            <ObjectXSDName>xxx.xsd</ObjectXSDName>
            <xxContractPayload>
                <xxxContract:InstrumentCore>
                    <xxxInstrument:AsOfDate>2016-07-15T12:22:40Z</xxxInstrument:AsOfDate>
                    <xxxInstrument:InstrumentRUID>16133645</xxxInstrument:InstrumentRUID>
                    <xxxInstrument:InstrumentName>Starbucks Corporation Dividend</xxxInstrument:InstrumentName>
                    <xxxInstrument:IssueStatus>Active</xxxInstrument:IssueStatus>
                </xxxContract:InstrumentCore>
            </xxContractPayload>
        </Object>

    </Event>
</xxxWrapper:yyyMMessage>]]></pre>

</td>
            <td>16133645</td>
            <td>2016-09-21T08:40:55.083Z</td>
            <td>2999-12-31T00:00:00Z</td>
            <td>7534ba96-d0de-4a61-a003-7b12289c28f5-0-83</td>
            <td>ld-20160920-100251850-27</td>
            <td>2016-09-21T08:42:40.189Z</td>
            <td>ld</td>
            <td>xxx_OWNER</td>
            <td>49c1fa7209e4c5c1e0e57c98d618f2ca883dd5813be2d2c6793a179f1716386f</td>
            <td>Y</td>
         </tr>
      </table>
   </body>
</html>

 

How do I apply an assertion on say : xxxInstrument:InstrumentRUID ?

 

Thanks in anticipation..

 

Amit

 

  • amit_db,

     

    Mr KarelHusa provided already a solution and a suggestion to use regular expression.

     

    Here is another way using Script Assertion:

     

     

    /**
    * Closure to search for certain element data
    * input parameters
    * xml data, element name to search
    **/
    def searchData = { data, element ->
       def parsedData = new XmlSlurper().parseText(data)
       parsedData.'**'.find { it.name() == element} as String
    }
    
    //Check if there is any thing in response
    assert context.response, "Response is empty or null"
    
    //Get the cdata part which is inside element "pre"
    def cData = searchData(context.response,'pre')
    assert cData, "CDATA is empty or null"
    
    //Get the instrumentId from cdata
    def instrumentId = searchData(cData, 'InstrumentRUID')
    
    //Check if that is matching.
    assert '16133645' == instrumentId, "InstrumentId is not matching"
  • nmrao's avatar
    nmrao
    Champion Level 3

    amit_db,

     

    Mr KarelHusa provided already a solution and a suggestion to use regular expression.

     

    Here is another way using Script Assertion:

     

     

    /**
    * Closure to search for certain element data
    * input parameters
    * xml data, element name to search
    **/
    def searchData = { data, element ->
       def parsedData = new XmlSlurper().parseText(data)
       parsedData.'**'.find { it.name() == element} as String
    }
    
    //Check if there is any thing in response
    assert context.response, "Response is empty or null"
    
    //Get the cdata part which is inside element "pre"
    def cData = searchData(context.response,'pre')
    assert cData, "CDATA is empty or null"
    
    //Get the instrumentId from cdata
    def instrumentId = searchData(cData, 'InstrumentRUID')
    
    //Check if that is matching.
    assert '16133645' == instrumentId, "InstrumentId is not matching"
    • amit_db's avatar
      amit_db
      New Contributor

      Hi Rao,

       

      Thanks for the solution, it worked for me. One more question, what if I want to assert the value of an element from an external source, like an excel or DB ?

       

      Thanks,

      Amit

    • amit_db's avatar
      amit_db
      New Contributor

      Hi Rao,

       

      In the solution you provided, could you please explain what is the following line doing:

       

      parsedData.'**'.find { it.name() == element}

       

      What does the ** mean here ?

       

       

       

      Thanks,

      Amit

  • KarelHusa's avatar
    KarelHusa
    Champion Level 1

    I would suggest to make a Script assertion and do the following:

    1. parse HTML (if it is an XHTML)

    2. get the CDATA content

    3. build an XML document out of it

    4. get the node value and make assertion

     

    def response = messageExchange.getResponseContent()
    def html = new XmlSlurper(false, false).parseText(response)
    def xml = html.body.table.tr[1].td[0].pre.toString()
    def yyyMMessage = new XmlSlurper(false, false).parseText(xml)
    assert yyyMMessage.Event.Object.ContractPayload.InstrumentCore.InstrumentRUID.toString() == "16133645"

    Another option is to assert with a regular expression instead of parsing XML. I would recommend this if you cannot rely that the HTML content is well formed XML.

     

  • nmrao's avatar
    nmrao
    Champion Level 3

    Here is the way to go with regular expression approach using Script Assertion

     

    /**
    * This is a Script Assertion 
    * using regex to check if InstrumentRUID has sequence of numbers
    **/
    
    //Check if there is response
    assert context.response, "Response is empty or null"
    
    //Define the regex
    def regEx = "<\\w+:InstrumentRUID>\\d+<\\/\\w+:InstrumentRUID>"
    
    //Get the match count
    def result =  (context.response =~ regEx)
    //Equal to 1, because there must be one match.
    log.info "Match count: ${result.count}"
    
    assert 1 == result.count, "InstrumnetRUID element do not match"