I have a SOAP request which has dynamic values generated by random method. How to capture these generated values to log?
My SOAP request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
<web:ChangeLengthUnit>
<web:LengthValue>${=(int)(Math.random()*9999)}</web:LengthValue>
<web:fromLengthUnit>Inches</web:fromLengthUnit>
<web:toLengthUnit>Centimeters</web:toLengthUnit>
</web:ChangeLengthUnit>
</soap:Body>
</soap:Envelope>
Groovy script:
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
Above groovy script is giving output as below:
Wed Oct 18 14:55:13 SGT 2017:INFO:[${=(int)(Math.random()*9999)}]
Actual value of LengthValue tag = 3490, How to get this value ?
It can easily read from RawRequest property using Script Assertion for the same request step.
assert context.rawRequest, 'Request is empty or null'
def xml = new XmlSlurper().parseText(context.rawRequest)
def actualValueInTheRequest = xml.'**'.find{it.name() == 'LengthValue'}?.text()
log.info "Value for LengthValue in the actual request is : $actualValueInTheRequest"
I think what you're doing is getting the LengthValue from the request 'template' not what SoapUI has actually passed to the web service.
In your example, you have...
def stepReq = tStep.getProperty("Request").getValue()
The request is what you see in SoapUI that includes your vars, e.g. ${myVar}. I think what you're after is the 'raw request'.
In SoapUI, run the request and after it has ran, you should see a tab labelled 'Raw Request'. This is what SoapUI actually sends to the web service, in here you'll see that the vars have been evaluated and will show the value, which is what you are after.
I've taken your example and made some mods it. I haven't tested it, but it should help you.
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
// CHA MOD - Can only get raw request after running the step.
def rawRequest = context.expand( '${ChangeLengthUnit#RawRequest}' )
//CHA MOD - Quick look at the rawRequest...
log.info(rawRequest);
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
//CHA MOD - Get the length from the raw request...
holder = groovyUtils.getXmlHolder( rawRequest.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
You are getting value from the actual request. Try to get the data from RawRequest
use below code
def holder = groovyUtils.getXmlHolder(mentionThenameofthestep#RawRequest)
The above code will point to Raw request of your teststep which contains actual value passed during execution instead of "${=(int)(Math.random()*9999)}"
Related
I am new to SOAP UI (using SOAP UI free version). I have a SOAP request XML and I need to run the same request multiple times passing different value for one tag each time. Can anyone please help me with the Groovy script that can be used here.
You can use the below sample to do the same. place all your test condition on local and fetch and run one-by-one
import com.eviware.soapui.support.XmlHolder;
import groovy.io.FileType;
import java.nio.file.Files;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
// Folder location , where input files are present, can be change or replace with new location. but same location has to be given here.
def sInputXMLpath = "C:\\TestFilesFolder\\RequestFiles\\"
// Test suites name : can be change or replace with new name. but same location has to be given here.
def sTestSet = testRunner.testCase.testSuite.project.testSuites["Demo"]
//if you have mutliple test cases, please change the index..... it will start with 0..( being first test case )
def sTestCase = sTestSet.getTestCaseAt(0)
log.info "TestCase.name : " + sTestCase.name
def iCountTestSteps = sTestCase.getTestStepCount()
log.info "Total Test Count of Test Steps in your TestSuite : " + iCountTestSteps
def i = 1
new File(sInputXMLpath).eachFile
{
def sInputFileName = it.name[0..-1]
log.info "Processing the file " + sInputFileName
log.info "**********************************************************************"
log.info "Test Number_"+ i +"_is Executing"
log.info "**********************************************************************"
log.info "Request of InputFileName : " + sInputFileName + " Is Executing "
def sTrimName = sInputFileName
sInputFileName = sTrimName.replaceAll(".xml","")
sInputFileContent = it.getText('UTF-8')
sTestCase.getTestStepAt(0).getProperty("Request").setValue(sInputFileContent);
//log.info "Request content : " + sTestCase.getTestStepAt(0).getProperty("Request").getValue()
testRunner.runTestStepByName("TestStepforRequest")
log.info "Info :TestStepforRequest get Called "
i++
}
In SoapUI speak, this is a data-driven test. SoapUI Pro version has really good support for this, but it is not enabled in the free version.
This is a rather common question on Stack Overflow, see this post which also includes a link to a page which describes how you can 'bend' the free version to run data-driven tests.
If you're not tied to SopaUI, you might want to try Postman. The free version of Postman has data-driven tests out of the box. See this link from the Postman site about using data files for testing.
I have a requirement to write a results (Pass/Fail) in the same excel sheet where the script reads the parameter in a FOR loop. It is throwing an error:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'jxl.read.biff.WorkbookParser#3da0525b' with class 'jxl.read.biff.WorkbookParser' to class 'jxl.write.WritableWorkbook' error at line: 16
My code:
import jxl.*;
import jxl.write.*;
import java.io.*;
import groovy.json.JsonSlurper
//Get project path
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def projectPath = groovyUtils.projectPath
def testCaseName = testRunner.testCase.name
//Read excel file and get the input value
WritableWorkbook xlwb = Workbook.getWorkbook(new File ("${projectPath}\\${testCaseName}.xls"))
Sheet inputxlsh = xlwb.getSheet(0)
inputRowCount = inputxlsh.getRows();
WritableSheet outputxlsh = xlwb.getSheet(1)
outputRowCount = outputxlsh.getRows();
log.info "Executing Test Case " + testCaseName
log.info "Total records to send API request to webservice from the file : " + inputRowCount -1
for (i=0;i<inputRowCount-1;i++)
{
Cell requestParam1 = inputxlsh.getCell(0,i+1)
affkey = requestParam1.getContents()
Cell requestParam2 = inputxlsh.getCell(1,i+1)
etid = requestParam2.getContents()
def soapTestCase = context.testCase
//Set the request property value (Parameter)
requestPropertyVariable = soapTestCase.getTestStepByName("requestProperty")
requestPropertyVariable.setPropertyValue("affkey",affkey)
requestPropertyVariable.setPropertyValue("etid",etid)
log.info "Reading record " + (i+1) + " from input file"
log.info "Sending request with affkey " + affkey
log.info "Sending request with etid " + etid
//Post a request to webservice
def responseContent = testRunner.runTestStepByName("showetidRequest").getResponse()
def responseText = responseContent.getContentAsString()
//Save the output file
def fileObj = new File("${projectPath}\\API_Response\\${testRunner.testCase.name}\\${etid}_Response.txt")
saveToFile(fileObj, responseText)
//Get the response value
JsonSlurper jsonResponseContent = new JsonSlurper()
def jsonResponseObject = jsonResponseContent.parseText(responseText)
//Validate results
Cell headerParam1 = outputxlsh.getCell(0,0)
Cell headerParam2 = outputxlsh.getCell(1,0)
Cell headerParam3 = outputxlsh.getCell(2,0)
Cell headerParam4 = outputxlsh.getCell(3,0)
Cell headerParam5 = outputxlsh.getCell(4,0)
Cell headerParam6 = outputxlsh.getCell(5,0)
for (k = 0; k < outputRowCount-1; k++) {
Cell responseParam1 = outputxlsh.getCell(0,k+1)
Cell responseParam2 = outputxlsh.getCell(1,k+1)
Cell responseParam3 = outputxlsh.getCell(2,k+1)
Cell responseParam4 = outputxlsh.getCell(3,k+1)
Cell responseParam5 = outputxlsh.getCell(4,k+1)
Cell responseParam6 = outputxlsh.getCell(5,k+1)
expectedAffiliatesWithContent = responseParam1.getContents()
expectedEntityName = responseParam2.getContents()
expectedName = responseParam3.getContents()
expectedSaleMessageId = responseParam4.getContents()
expectedTitle = responseParam5.getContents()
expectedetid = responseParam6.getContents()
if(etid==expectedetid){
responseAffiliatesWithContent = jsonResponseObject.AffiliatesWithContent.getAt(0).getAt(0)
responseEntityName = jsonResponseObject.Genre.EntityName.getAt(0)
responseName = jsonResponseObject.Genre.Name.getAt(0)
responseSaleMessageId = jsonResponseObject.SaleMessage.Id.getAt(0)
responseTitle = jsonResponseObject.Title.getAt(0)
log.info responseAffiliatesWithContent
log.info responseEntityName
log.info responseName
log.info responseSaleMessageId
log.info responseTitle
if (responseAffiliatesWithContent==expectedAffiliatesWithContent&&responseEntityName==expectedEntityName&&responseName==expectedName&&responseSaleMessageId==expectedSaleMessageId&&
responseTitle==expectedTitle)
{
log.info "The data is matched for record " + (k +1) + " hence test case passed "
Label l = new Label(7, k +1, "Pass");
outputxlsh.addCell(l);
xlwb.write();
}
else {
log.info "The data is matched for record " + (k +1) + " hence test case failed "
}
}
}
}
//Clear Property
requestPropertyVariable.setPropertyValue("affkey","")
requestPropertyVariable.setPropertyValue("etid","")
//Write file method
def saveToFile(fileObj, content) {
if (!fileObj.parentFile.exists()) {
fileObj.parentFile.mkdirs()
}
fileObj.write(content)
log.info "Response for etid " + etid + " is stored in " + "${etid}_Response.txt"
assert fileObj.exists(), "${fileObj.name} not created"
}
If you want a write able copy call createWorkbook function
WritableWorkbook xlwb = Workbook.createWorkbook(new File ("${projectPath}\\${testCaseName}.xls"))
If you don't want write able copy save in Workbook object instead
Workbook workbook = Workbook.getWorkbook((new File ("${projectPath}\\${testCaseName}.xls"))
I have achieved the requirement based on below code
def inptDataWb = new HSSFWorkbook(xlwb);
def inputxlsh = inptDataWb.getSheetAt(2);
wrtResult = outputxlsh.getRow(k+1).getCell(3);
wrtResult.setCellValue("P");
wrtResult = outputxlsh.getRow(k+1).getCell(5);
wrtResult.setCellValue("");
inptDataWb.write(xlOwb);
I'm gonna include the xml structure below:
#Rao, #tim_yates. The actual xml is:
<prnReq>
<ltrPrnReqs>
<ltrPrnReq>
<ltrData>encoded64 text</ltrData>
</ltrPrnReq>
</ltrPrnReqs>
</prnReq>
I need to include a new Node in . The new XML must be:
<prnReq>
<ltrPrnReqs>
<ltrPrnReq>
<ltrData>
<Salutation>text</Salutation>
</ltrData>
</ltrPrnReq>
</ltrPrnReqs>
</prnReq>
The question is how to append a new node in ?
I've found many samples how to use appendNode, however, it is always a
root.child. I need to go further in my XML structure and append a node at
prnReq.ltrPrnReqs.ltrPrnReq.ltrData
the node to be included is <salutation>
Any comments are welcome.
Below the current code.
Many thanks!
import groovy.xml.QName
import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil
File doc = new File("C:/Temp/letter_.xml")
def prnReq = new XmlSlurper().parse(doc)
prnReq.ltrPrnReqs.ltrPrnReq.each {
def encodedString = it.ltrData.toString()
Base64.Decoder decoder = Base64.getMimeDecoder()
byte[] decodedByteArray = decoder.decode(encodedString)
def output = new String(decodedByteArray)
println output
output.splitEachLine(';') { items ->
println "raSalutation: " + items[0]
println "raFromAcc: " + items[1]
println "raPayableTo: " + items[2]
println "raSortCode: " + items[3]
println "raAccNum: " + items[4]
println "raReference: " + items[5]
println "raSendDate: " + items[6]
println "raRecDate: " + items[7]
println "raAmount: " + items[8]
println "raDummy1: " + items[9]
println "raFirstAmt: " + items[10]
println "raFirstDate: " + items[11]
println "raRegularAmt: " + items[12]
println "raRegularDate: " + items[13]
println "raFrequency: " + items[14]
println "raFee: " + items[15]
def toAdd = '"<salutation>$item[0]</salutation>"'
fragToAdd = new XmlSlurper().parseText(toAdd)
prnReq.ltrPrnReqs.ltrPrnReq.ltrData.appendNode(fragToAdd)
}
String outputFileName = "C:/Temp/letter_.xml"
XmlUtil xmlUtil = new XmlUtil()
xmlUtil.serialize(prnReq, new FileWriter(new File(outputFileName)))
}
You should be able to add the new node using appendNode.
Here is complete sample showing how to do it.
def xmlString = """<prnReq>
<ltrPrnReqs>
<ltrPrnReq>
<ltrData>encoded64 text</ltrData>
</ltrPrnReq>
</ltrPrnReqs>
</prnReq>"""
def xml = new XmlSlurper().parseText(xmlString)
def ltrData = xml.'**'.find{it.name() == 'ltrData'}
ltrData.replaceBody()
ltrData.appendNode {
Salutation('text')
}
println groovy.xml.XmlUtil.serialize(xml)
You can quickly try it online demo
I am generating a file where it should output 2 various requests and 2 various responses from different SOAP Request steps which are:
TestRegion
TestRules
However I noticed the file is just generating TestRegion request and response 2 times each over. For each request it displays TestRegion request and for each response it's displaying TestRegion response. Why is it doing this and how can I get the correct request and responses to show? it does display the hard coded strings correct like TESTREGION REQUEST: and then later on TEST REGION RESPONSE, but the request and response is incorrect.
def testRegionRequest = context.expand( '${${TestRegion}#Request}' )
def testRegionResponse = context.expand( '${${TestRegion}#Response}' )
def testRulesRequest = context.expand( '${${TestRules}#Request}' )
def testRulesResponse = context.expand( '${${TestRules}#Response}' )
def fileName = "XXX.txt"
def logFile = new File(fileName)
//Draws a line
def drawLine(def letter = '=', def count = 70) { letter.multiply(count)}
def testResult = new StringBuffer()
testResult.append drawLine('-', 60) + "\n\n"
testResult.append "\n\nTEST REGION REQUEST:\n\n"
testResult.append(testRegionRequest.toString())
testResult.append "\n\n" + drawLine('-', 60) + "\n\n"
testResult.append "\n\nTEST REGION RESPONSE:\n\n"
testResult.append(testRegionResponse.toString())
testResult.append "\n\n" + drawLine('-', 60) + "\n\n"
testResult.append "\n\nTEST RULES REQUEST:\n\n"
testResult.append(testRulesRequest.toString())
testResult.append "\n\n" + drawLine('-', 60) + "\n\n"
testResult.append "\n\nTEST RULES RESPONSE:\n\n"
testResult.append(testRulesResponse.toString())
// Now create and record the result file
logFile.write(testResult.toString())
It appears that you have incorrect values used in the context.expand
Change from:
${${SearchRegion}#Request}
To:
${SearchRegion#Request}
And the same is applicable to other properties as well.
My groovy code is as below. I can get request and response when I use the real test step name in the:
def request=context.expand('${"testStepName"#request}')
def response=context.expand('${"testStepName"#response}')
When I change to use variable:
def request=context.expand('${${currentStep.name}#request}')
def response=context.expand('${${currentStep.name}#response}')**
I can only get request, while fail to get response. The error is
org.apacge.xmlbeans.XmlException: error: unexpected end of file after null
error at line: xx
The test step that currentStep points to has been executed and has request/reponse.
Can anyboby here kindly help me?
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext
import groovy.sql.Sql
import oracle.jdbc.driver.OracleTypes
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
def currentStep = testRunner.testCase.getTestStepAt(6)
log.info "currentStep.name: " + currentStep.name
// get the hold of request
def request=context.expand('${${currentStep.name}#request}')
log.info " request: " + request
// get the desired node value from request
def xmlreq=new XmlHolder(request)
// get the hold of response
def response=context.expand('${${currentStep.name}#response}')
log.info " response: " + response
// get the desired node value from response
def xmlres=new XmlHolder(response)
I solved my issue efter reading the message.
http://community.smartbear.com/t5/SoapUI-NG/Resolved-Pass-a-variable-into-context-expand-code/td-p/43025
String propertySpec = '${' + currentStep.name + '#Response}'
log.info "propertySpec : ${propertySpec}"
def response = context.expand(propertySpec)
log.info("context.expand(propertySpec) : ${response}")
def xmlres=new XmlHolder(response)