JesseN
JesseN

Reputation: 47

Compare JDBC Response to an XML Response where number of nodes vary and order could change?

I am very new to coding and am having some trouble when attempting to compare the results from a JDBC query to the results in an XML response.

I am using groovy rather than XPATH built into SoapUI because based on the parameters passed in my request, the number of nodes returned could vary and I need to validate all of them.

I built the script below using various examples that I found since I could not find one single example that was going to do what I wanted. I plugged in everything from the class tag down into eclipse and it did not detect any syntax errors. However, when I run the script in SoapUI, when it reaches the part to parse the xml response, nothing is built. Then my validations and assertions fail of course. The JDBC data built just fine.

Thanks in advance for any assistance.

import com.eviware.soapui.support.XmlHolder
import groovy.xml.XmlUtil
import groovy.util.XmlSlurper
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)


class Model {
    def campaignSysKey
    def campaignName
    def startDate
    def endDate
    def campaignCode

    def buildJdbcData(row) {
        row.with {
            campaignSysKey = UPGRADETYPE
            campaignName = SOURCEDESC
            startDate = STARTDATE
            endDate = ENDDATE
            campaignCode = SOURCECODE
        }
    }

    def buildXMLData(tagInfo) {
        campaignSysKey = tagInfo.@campaignSysKey
        campaignName = tagInfo.@campaignName
        startDate = tagInfo.@startDate
        endDate = tagInfo.@endDate
        campaignCode = tagInfo.@campaignCode
    }
}

def jdbcResponse = context.expand('${Validation#ResponseAsXml}')
def xmlResponse = context.expand('${OfferHistoryRequest#Response}')

def results = new XmlSlurper().parseText(jdbcResponse)
def jdbcDataObjects = []
results.ResultSet.Row.each { row ->
    jdbcDataObjects.add(new Model().buildJdbcData(row))
}

def arrayOfTagInfo = new XmlSlurper().parseText(xmlResponse)
def xmlDataObjects = []
arrayOfTagInfo.TagInfo.each { tagInfo ->
    xmlDataObjects.add(new Model().buildXMLData(tagInfo))
}

log.info "${jdbcDataObjects.size()}"
log.info "${xmlDataObjects.size()}"


if (jdbcDataObjects.size() != xmlDataObjects.size()) {
    log.info("Jdbc resultset size is : ${jdbcDataObjects.size()} and XML result size is : ${xmlDataObjects.size()}")

}


assert jdbcDataObjects == xmlDataObjects, "Comparison of JDBC and XML data is failed"

JDBC Response Structure:

<Results>
   <ResultSet fetchSize="0">
      <Row rowNumber="1">
         <UPGRADETYPE>1</UPGRADETYPE>
         <SOURCEDESC>Desc 1</SOURCEDESC>
         <STARTDATE>2015-01-01</STARTDATE>
         <ENDDATE>2017-12-31</ENDDATE>
         <SOURCECODE>ABC123</SOURCECODE>
      </Row>
      <Row rowNumber="2">
         <UPGRADETYPE>2</UPGRADETYPE>
         <SOURCEDESC>Desc 2</SOURCEDESC>
         <STARTDATE>2015-01-01</STARTDATE>
         <ENDDATE>2017-12-31</ENDDATE>
         <SOURCECODE>XYZ987</SOURCECODE>
      </Row>
   </ResultSet>
</Results>

XML Response (Removed data between the Holding tags intentionally, but left them in to show structure of response. I am only concerned with the Campaign nodes):

<soap:Envelope xmlns:soap="http://sample.org">
   <soap:Body>
      <TXLife xmlns="http://sample.org">
         <TXLifeResponse>
            <TransRefGUID>123456</TransRefGUID>
            <TransType tc="999"/>
            <TransSubType tc="9909"/>
            <BusinessService DataRep="VIEW"/>
            <TransExeDate>2017-01-19-05:00</TransExeDate>
            <TransExeTime>09:19:30.668-05:00</TransExeTime>
            <StartRecord>1</StartRecord>
            <TransResult>
               <ResultCode tc="1"/>
               <RecordsFound>2</RecordsFound>
            </TransResult>
            <OLifE>
               <Holding id="Holding_B1234567">                  
               </Holding>
               <Campaign id="Campaign_B1234567_1" AppliesToCoverageID="Coverage_B1234567_1">
                  <CampaignSysKey>1</CampaignSysKey>
                  <CampaignName>Desc 1</CampaignName>
                  <StartDate>2015-01-01</StartDate>
                  <EndDate>2017-12-31</EndDate>
                  <CampaignCode>ABC123</CampaignCode>
               </Campaign>
               <Campaign id="Campaign_B1234567_2" AppliesToCoverageID="Coverage_B1234567_2">
                  <CampaignSysKey>2</CampaignSysKey>
                  <CampaignName>Desc 2</CampaignName>
                  <StartDate>2015-01-01</StartDate>
                  <EndDate>2017-12-31</EndDate>
                  <CampaignCode>XYZ987</CampaignCode>
               </Campaign>
            </OLifE>
         </TXLifeResponse>
      </TXLife>
   </soap:Body>
</soap:Envelope>

Error from SoapUI Log:

Thu Jan 19 10:00:31 EST 2017:ERROR:java.lang.AssertionError: Comparison of JDBC and XML data is failed. Expression: (jdbcDataObjects == xmlDataObjects). Values: jdbcDataObjects = [X34143, X33582], xmlDataObjects = []
   java.lang.AssertionError: Comparison of JDBC and XML data is failed. Expression: (jdbcDataObjects == xmlDataObjects). Values: jdbcDataObjects = [X34143, X33582], xmlDataObjects = []
    at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:404)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:650)
    at Script5.run(Script5.groovy:67)
    at com.eviware.soapui.support.scripting.groovy.SoapUIGroovyScriptEngine.run(SoapUIGroovyScriptEngine.java:92)
    at com.eviware.soapui.support.scripting.groovy.SoapUIProGroovyScriptEngineFactory$SoapUIProGroovyScriptEngine.run(SoapUIProGroovyScriptEngineFactory.java:79)
    at com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep.run(WsdlGroovyScriptTestStep.java:156)
    at com.eviware.soapui.impl.wsdl.panels.teststeps.GroovyScriptStepDesktopPanel$RunAction$1.run(GroovyScriptStepDesktopPanel.java:274)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Upvotes: 1

Views: 1351

Answers (1)

Rao
Rao

Reputation: 21369

Here is the script which I corrected to make it work.

The problems in the script you made and addressed as below -

  • xml elements are not read properly
  • made the methods static
  • Canonical annotation added to class so that it allows to comparable

Groovy Script

//Class to model the different sources of data and create object
//so that those are comparable
@groovy.transform.Canonical
class Model {
    String campaignSysKey
    String campaignName
    String startDate
    String endDate
    String campaignCode

    static def buildJdbcData(row) {
        def obj = new Model()
        row.with {
            obj.campaignSysKey = UPGRADETYPE
            obj.campaignName = SOURCEDESC
            obj.startDate = STARTDATE
            obj.endDate = ENDDATE
            obj.campaignCode = SOURCECODE
        }
        obj
    }

    static def buildXMLData(cmpgn) {
        def obj = new Model()
        obj.campaignSysKey = cmpgn.CampaignSysKey as String
        obj.campaignName = cmpgn.CampaignName as String
        obj.startDate = cmpgn.StartDate as String
        obj.endDate = cmpgn.EndDate as String
        obj.campaignCode = cmpgn.CampaignCode as String
        obj
    }
}

//Read the jdbc response from its step 
def jdbcResponse = context.expand('${Validation#ResponseAsXml}')

//Read the xml response from its step
def xmlResponse = context.expand('${OfferHistoryRequest#Response}')

//Read & Create objects for jdbc response
def results = new XmlSlurper().parseText(jdbcResponse)
def jdbcDataObjects = []
results.ResultSet.Row.each { row ->
    jdbcDataObjects.add(Model.buildJdbcData(row))
}

//Read & Create objects for xml response
def parsedXml = new XmlSlurper().parseText(xmlResponse)
def campaigns = parsedXml.'**'.findAll{it.name() == 'Campaign'}
def xmlDataObjects = []
campaigns.each { cmpgn ->
    xmlDataObjects.add(Model.buildXMLData(cmpgn))
}

//Log both responses
log.info "Jdbc response records: ${jdbcDataObjects.size()}"
log.info "Xml response records: ${xmlDataObjects.size()}"


if (jdbcDataObjects.size() != xmlDataObjects.size()) {
    log.info("Jdbc resultset size is : ${jdbcDataObjects.size()} and XML result size is : ${xmlDataObjects.size()}") 
}

//Check if both object sizes are equal before comparing one to one
assert jdbcDataObjects.size() == xmlDataObjects.size(), "Both responses have not matched element count"

//Log both the objects
log.info jdbcDataObjects.toString()
log.info xmlDataObjects.toString()

//Compare now both the responses and show the difference
if (jdbcDataObjects != xmlDataObjects){
    log.info "Both responses do not match"
    for(int index=0;index<jdbcDataObjects.size();index++){
        assert jdbcDataObjects[index] == xmlDataObjects[index], "Responses @ ${index+1} position do not match"
    }
} else {
    log.info "Both responses matches"
}

By the way, the responses you posted have difference.

If you want to quickly check online demo

Upvotes: 0

Related Questions