Forum Discussion

HaroldR's avatar
HaroldR
Contributor
7 years ago
Solved

Get all Nodes Names and values from a test case Response

Hello @All,

 

i am trying to retrieve Node names and values from a SOAP response received by a webservice's method that I test.

Here is my code and I attach the output as a file:

import groovy.util.XmlSlurper;
import groovy.util.slurpersupport.*;

// create groovyUtils and XmlHolder for response of the request
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def requestResponse = groovyUtils.expand('${CheckSdcAuthorisation[8.2]#Response}');
def holder = groovyUtils.getXmlHolder(requestResponse);
def parseResponse = new XmlSlurper().parseText(requestResponse);
def allNodeValues = holder.getNodeValues("//*");

// loop item nodes in response message
for( item in allNodeValues){
log.info "Item : [$item]"
}

The issue is that I'm not able to get node names and corresponding values. I do not understand why the for loop does not return Node values as expected? Also what code should I change to replace Item by the name of the node?
Do you have any suggestion to solve my issue?

  • This is going to require some groovy scripting, without a doubt. There's a feature that you can use in groovy to directly compare two xml statements called XMLUnit. You can see some of the specifics of it here and here.

     

    Here's a snippet of code that'll compare XML:

     

    import org.custommonkey.xmlunit.*;

    XMLUnit.setIgnoreWhitespace(true)
    XMLUnit.setIgnoreComments(true)
    XMLUnit.setIgnoreDiffBetweenTextAndCDATA(false)
    XMLUnit.setNormalizeWhitespace(true)

    def request1Xml = context.expand( '${Request1#Response}' )
    def request2Xml = context.expand( '${Request2#Response}' )

    Diff diff = new Diff (request1Xml, request2Xml);

    DetailedDiff myDiff = new DetailedDiff (diff);

    log.info(myDiff);

    This will give a relatively detailed difference between the two XML responses. That might give you what you want.

17 Replies

  • groovyguy's avatar
    groovyguy
    Champion Level 1

    What use case are you trying to build here with this script? Groovy scripts are powerful, but can become very complex very quickly and may actually be a bad solution in some cases.

  • nmrao's avatar
    nmrao
    Champion Level 3
    I believe that you had some question earlier, might be related? it was said that you wanted to compare, and it is marked answered.
  • nmrao's avatar
    nmrao
    Champion Level 3
    By the way, all nodes can't have values i.e., complex nodes inturn have child nodes as values.

    It would be appreciated if you provide more details on what are you trying to achieve, then some one will be in a good position to offer better help.
    • groovyguy's avatar
      groovyguy
      Champion Level 1

      I threw together a groovy script that I've been working on for my own use that fits what you are looking for. This script will parse every element in the Body of the response that contains actual data. Adjust as necessary.

       

      import groovy.util.XmlSlurper;
      import groovy.util.slurpersupport.*;
      
      // create groovyUtils and XmlHolder for response of the request
      def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
      def requestResponse = groovyUtils.expand('${ChangedSinceDate#Response}');
      def holder = groovyUtils.getXmlHolder(requestResponse);
      def parseResponse = new XmlSlurper().parseText(requestResponse);
      
      // loop item nodes in response message
      
      def mapConstruct(mapNodes) {
          mapNodes.children().collectEntries 
          { 
              [ 
              	it.name(), it.childNodes() ? mapConstruct(it) : it.text() 
              ] 
          }
      }
      
      def parseMaps(Map map, int counter = 0, org.apache.log4j.Logger log)
      {
      	map.each
      	{
      		k, v -> 
      		// log.info("$k");
      		if (v.getClass().toString() == "class java.util.LinkedHashMap")
      		{
      			// log.info("recurse case $v");
      			parseMaps(v, counter++, log);
      		}
      		else
      		{	
      			// log.info("base case");
      			if (v.size() > 0)
      			{
      				log.info("$k has a value of $v");
      			}
      		}
      	}
      }
      
      def map = mapConstruct(parseResponse);
      
      log.info(map.getClass());
      
      String [] keySet = map.keySet().toArray();
      
      log.info(keySet.size());
      
      parseMaps(map["Body"], 0, log);
      
      
      • HaroldR's avatar
        HaroldR
        Contributor

        Thanks for you replies both! Yes, my issue is not solved at all nmrao but as the topic of my preceding subject was particular and the reply of groovyguy was related to what I aked, I marked it as solve.

        I did not take the time to take a look on your script groovyguy but I will, and really thanks to have shared it for my use.

        I will precise my need, maybe you could help me to think and tell me about the best method to do it.

        In my work, following the migration of a web service, I have to send a wide range of requests in order to be the most exhaustive as possible to test two differents binding interface. The requests sent must be exactly the same from one binding interface to the other.

        My test must idenfy the discrepancies between both received response. So what's the best method to achieve that ?

        Knowing that, in general cases where everything is good, I can create a simple contains assertion based on a "Get Data" retrieving which permit me to compare the content of both responses.


        In particular cases, where services integrate business logic, I am forced to use a complex message assertion which I set line by line.
        In my test case, I create 4 steps :
        1) Response from first binding interface.
        2) A propety transfer step where I create a transfer value for each node in my xml response from the first binding interface. 3) A properties step where I created a property for each node value (the name of the property is the name of my node) and the value is filled thanks to my property transfer step.
        4) Response from the second binding inteface where the complex message assertion is set. This allow me to compare the expected result from Response1 (Node value) to the actual result (Node value from Response 2) one by one.
        Reasoning is pretty simple, but the issue appears when responses received are really long for instance thousands of xml line; it takes me hours and sometimes days to build my test, and it's really heavy to implement it.

        As I'm new in testing domain in using SoapUI Pro and not so familiar in programming languages in general and especially in groovy, it's really complicated for me to set up an automated process to point out every difference from this use case.
        Moreover, as I'm alone as tester in my team, I need to build everything by myself, and my technical knowledge does not permit me to find the best way to achieve my purpose.

        So let's discuss about your suggestions, you have really more experience than I have so may be you will have some ideas and show me the best way to avoid wasting time!

        If you need more details, I would be happy to provide you more.
        Also, do not hesitate to tell me if I did not present the subject clearly.

        I hope that we wil have a great collaboration together!


  • Mohan_hbk's avatar
    Mohan_hbk
    Occasional Contributor

    My issue is, I have two SOAP responses I wanted to compare node values in one response with other Soap response. Problem I am facing is Nodenames are different but data present in nodes are same.How can I compare? will xmlunit help solving this?

    • groovyguy's avatar
      groovyguy
      Champion Level 1

      Mohan_hbk : You may want to consider starting your own thread with details specific to your question and problem at hand. :)