Automatic Data Driven tests in SoapUI via Groovy Script - groovy

as discussed HERE in soapUI free version i'm trying to call this WS:
<soap:Body>
<RequestParameters>
<Parameter name="key" value="SomeorderId"/>
</RequestParameters>
</soap:Body>
and i want to take the values of "key" from a local data.txt file on my desktop. the content of this file:
9999999991
9999999992
9999999993
to do so, i've created a test suite with below three test steps:
1.first step: a groovy script:
def data = new File('C:/Users/Polarick/Desktop/data.txt')
data.eachLine { orderId ->
context.orderId = orderId
//Get the step2, index of the step is 1
def step = context.testCase.getTestStepAt(1)
//Run the step2
step.run(testRunner, context)
}
//all the orders got executed,jump to step2, index is 2
testRunner.gotoStep(2)
2.second step: modifying request:
<Parameter name="MSISDN" value="${orderId}"/>
and asserting this script to it:
//Check if there is response
assert context.request, "Request is empty or null"
//Save the contents to a file
def saveToFile(file, content) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
log.info "Directory did not exist, created"
}
file.write(content)
assert file.exists(), "${file.name} not created"
}
def response = context.expand( '${Step2#Response}' )
def f = new File("C:/Users/Polarick/Desktop/${context.orderId}_Response.xml")
f.write(response, "UTF-8")
saveToFile(f, context.response)
3.Third step: a groovy script:
log.info "Test completed."
It all works fine and calls the WS for all lines existing in data.txt file sequentially, but i'm expecting to find a response .xml file per execution, for example:
C:/Users/Polarick/Desktop/9999999991_Response.xml
C:/Users/Polarick/Desktop/9999999992_Response.xml
C:/Users/Polarick/Desktop/9999999993_Response.xml
but there is no response file generated,
can you help?

Related

Groovy to validate the list of node values with the values stored in a property step

Properties ScreenshotResponse Snippet
<tns:TAResponse
xmlns:tns="http://webconnectivity.co.uk/">
<tns:SessionToken>84hjfutryh47849dkdhg9493493=</tns:SessionToken>
<tns:PartyId>1234</tns:PartyId>
<tns:ResponseType></tns:ResponseType>
<tns:MessageUUId>12341F17-ABC9-3E99-1D12-B8289POO2107</tns:MessageUUId>
<tns:Matches>
<tns:IntegrationServiceMatch>
<tns:InternalReference>2066856</tns:InternalReference>
<tns:ErrorsAndWarnings>
<tns:IntegrationServiceErrorCode>
<tns:ErrorCode>W000026</tns:ErrorCode>
<tns:Description>Settlement Date not within tolerance</tns:Description>
</tns:IntegrationServiceErrorCode>
<tns:IntegrationServiceErrorCode>
<tns:ErrorCode>E000033</tns:ErrorCode>
<tns:Description>Number on message does not match</tns:Description>
</tns:IntegrationServiceErrorCode>
<tns:IntegrationServiceErrorCode>
<tns:ErrorCode>E000001</tns:ErrorCode>
<tns:Description>NO likely matches</tns:Description>
</tns:IntegrationServiceErrorCode>
</tns:ErrorsAndWarnings>
</tns:IntegrationServiceMatch>
</tns:Matches>
</tns:TAResponse>
I have stored all these Errorcode and Description in a property step. I need to validate whether these Errorcode and Description in the response matches with the property step. (sequence is not a deal)
Can someone pls guide me through groovy?
Previously i had to validate only one errorcode and desc from the response. so i validated using below script.
def content = new XmlSlurper().parse(file)
def respType = content.Body.TAResponse.ResponseType.text()
def errAndWarn = content.Body.TAResponse.Matches.IntegrationServiceMatch
assert errAndWarn.size() == 1
for (def i=0;i<errAndWarn.size();i++)
{
assert errAndWarn[i].ErrorsAndWarnings.IntegrationServiceErrorCode.ErrorCode == "E000033"
assert errAndWarn[i].ErrorsAndWarnings.IntegrationServiceErrorCode.Description == "Number on message does not match"
}
You can use below Script Assertion for the SOAP Request test step itself, that will avoid additional Groovy Script test step.
This assumes that the name of the Properties test step name is Properties. If its name differs, then change in the script accordingly.
Script Assertion
//Change the name of the Properties test step below
def step = context.testCase.testSteps['Properties']
//check if the response is not empy
assert context.response, 'Response is empty or null'
//Parse the xml
def parsedXml = new XmlSlurper().parseText(context.response)
//Get the all the error details from the response as map
def errorDetails = parsedXml.'**'.findAll { it.name() == 'IntegrationServiceErrorCode'}.inject([:]){map, entry -> map[entry.ErrorCode.text()] = entry.Description.text(); map }
log.info "Error details from response : ${errorDetails}"
//loop thru xml error codes and verify against the properties of Properties Test Step
errorDetails.each { key, value ->
assert step.properties[key]?.value == value, "Unable to match value of the property ${key} "
}
EDIT: based on OP's comment
Groovy Script test step:
//Change the name of the Properties test step below
def step = context.testCase.testSteps['Properties']
//Parse the xml like you have in your script
def parsedXml = new XmlSlurper().parse(file)
//Get the all the error details from the response as map
def errorDetails = parsedXml.'**'.findAll { it.name() == 'IntegrationServiceErrorCode'}.inject([:]){map, entry -> map[entry.ErrorCode.text()] = entry.Description.text(); map }
log.info "Error details from response : ${errorDetails}"
//loop thru xml error codes and verify against the properties of Properties Test Step
errorDetails.each { key, value ->
assert step.properties[key]?.value == value, "Unable to match value of the property ${key} "
}
EDIT2: Based on additional requirement, adding below Groovy Script
//Change the name of the Properties test step below
def step = context.testCase.testSteps['Properties']
//Parse the xml like you have in your script
def parsedXml = new XmlSlurper().parse(file)
//Get the all the error details from the response as map
def errorDetails = parsedXml.'**'.findAll { it.name() == 'IntegrationServiceErrorCode'}.inject([:]){map, entry -> map[entry.ErrorCode.text()] = entry.Description.text(); map }
log.info "Error details from response : ${errorDetails}"
def failureMessage = new StringBuffer()
//Loop thru properties of Property step and check against the response
step.properties.keySet().each { key ->
if (errorDetails.containsKey(key)) {
step.properties[key]?.value == errorDetails[key] ?: failureMessage.append("Response error code discription mismatch. expected [${step.properties[key]?.value}] vs actual [${errorDetails[key]}]")
} else {
failureMessage.append("Response does not have error code ${key}")
}
}
if (failureMessage.toString()) {
throw new Error(failureMessage.toString())
}
You should be able to do:
content.Body
.TAResponse
.Matches
.IntegrationServiceMatch
.ErrorsAndWarnings
.IntegrationServiceErrorCode.each { node ->
println "Error code is ${node.ErrorCode.text()} and Description is ${node.Description.text()}"
}

how to write all Soap Request available in Project using Soap UI Groovy

I have a soap project with 4 Test Suite,each Test Suite has some Test Case and each Test case has some test steps[Soap Request,Groovy Script]
I am able to access all the properties using mentioned code below , HOWEVER,code is writing blank request/response file in local system **
def Project = testRunner.testCase.testSuite.project;
for(def i=0;i<Project.testSuiteCount;i++)
{
log.info Project.getTestSuiteAt(i).name
def Suite = Project.getTestSuiteAt(i)
for(def j=0;j<Suite.testCaseCount;j++)
{
log.info Suite.getTestCaseAt(j).name
def TCase = Suite.getTestCaseAt(j)
for(def k=0;k < TCase.testStepCount;k++)
{
def TStep= TCase.getTestStepAt(k)
def req = context.expand('${'+TStep.name+'#Request}')
new File("D:/Directory/"+Suite.name+"_"+TCase.name+"_"+TStep.name+"_"+k+".txt").write( req )
}
}
}
** plz help to solve this, **
Actually there are multiple approaches to achieve this.
Below is the one of the approach.
Here is Groovy Script which writes the requests and responses.
This script assumes that user has already run the test suites so that responses are available to be saved.
Create a new test suite -> test case -> add Groovy Script test step and copy the below script into it.
Groovy Script:
/**
* This groovy script saves the request and response
* And this script will be able to write the responses
* into files if and only if there is response available
**/
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
//Change direcoty path if required
def directoryToSave = 'D:/directory'
//Not required to change the script beyond this point
//date time is appended to the file name
def dt = new Date().format('yyyyMMdd_HHmmss')
//Closure to save the file
def saveToFile(file, content) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
log.info "Directory did not exist, created"
}
if (content) {
log.info "Writing the content into file :${file.name}"
file.write(content)
assert file.exists(), "${file.name} not created"
} else {
log.warn "the content is empty, not writing the content into file"
}
}
//Get the project object
def project = context.testCase.testSuite.project
//Loop thru the project and save the request and responses
project.testSuiteList.each { suite ->
suite.testCaseList.each { kase ->
kase.testStepList.each { step ->
if (step instanceof WsdlTestRequestStep) {
def reqFilePath = new File("${directoryToSave}/${suite.name}_${kase.name}_${step.name}_request${dt}.xml")
def resFilePath = new File("${directoryToSave}/${suite.name}_${kase.name}_${step.name}_response${dt}.xml")
saveToFile(reqFilePath, step.testRequest.requestContent)
saveToFile(resFilePath, step.testRequest.responseContent)
saveToFile(step)
} else {
log.info "Ignoring as the step type is not Soap request"
}
}
}
}

groovy.lang.MissingPropertyException: No such property: file for class: Script7 error at line 5

I am writing groovy script to save raw soap request & response and i get this error:
groovy.lang.MissingPropertyException: No such property: file for class: Script7 error at line 5
Here is the Script:
def myOutFile = context.expand( '${#TestSuite#fileName}' )+"_PostPaid-Success_Payment_BillInqReq.xml"
def response = context.expand( '${BillInq#Request}' )
def f = new File(myOutFile)
f.write(response, "UTF-8")
file.write(context.rawRequest,'utf-8')
Please follow the steps below:
Go to Test Suite PostPaid
Add a custom property say DATA_STORE_PATH and its value to a directory name where you like to save the requests and responses
Go to test case PostPaid_Success_Payment
Disable the Step 2 & Step 3 i.e., SaveInquiryReq and SaveInquiryResponse steps. or you may remove altoger as well if no other work is done apart from save the request & response respectively.
Click on step1 BillInq, click on assertions, Choose Script Assertion, see here for more details how to add script assertion
Have below script and click ok
Now you run the step1, you should be able to see the request and responses saved in the above mentioned directory
/**
* This script logs both request and response
*/
assert context.response, "Response is empty or null"
assert context.request, "Request is empty or null"
//Save the contents to a file
def saveToFile(file, content) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
log.info "Directory did not exist, created"
}
file.write(content)
assert file.exists(), "${file.name} not created"
}
def dirToStore = context.expand('${#TestSuite#DATA_STORE_PATH}')
def currentStepName = context.currentStep.name
def requestFileName = "${dirToStore}/${currentStepName}_request.xml"
def responseFileName = "${dirToStore}/${currentStepName}_response.xml"
//Save request & response to directory
saveToFile(new File(requestFileName), context.rawRequest)
saveToFile(new File(responseFileName), context.response)

How to export pdf attachment from soap response using groovy?

Although soap (free version) has an option to export document generated in response. Is there any groovy function to extract application/pdf file and store in my local folder ?
The following script should be able to save the attachment to a file.
Add the below script as Script Assertion to the current request step. Find the appropriate comments inline.
Source for the script is taken from here
/**
* Below script assertion will check
* if the response is not null
* there is an attachment
* and saves file to the specified location, by default saves into system temp
* directory
**/
//change file name as needed
def fileName = System.getProperty('java.io.tmpdir')+'/test.pdf'
//Get the response and check if the response is not null
def response = messageExchange.response
assert null != response, "response is null"
//Create output stream
def outFile = new FileOutputStream(new File(fileName))
//Check if there is one attachment in the response
assert 1 == messageExchange.responseAttachments.length, "Response attachments count not matching"
def ins = messageExchange.responseAttachments[0]?.inputStream
if (ins) {
//Save to file
com.eviware.soapui.support.Tools.writeAll( outFile, ins )
}
ins.close()
outFile.close()

Executing a Java jar file from within a SoapUI groovy script not working

I am new to SoapUI and Groovy so please forgive this post as it has been posted a number of times in Stackoverflow however I cannot find a fix.
SoapUI version: 4.5.2
I have 2 questions if you guys don't mind:
I have an executable jar file that I've put in the the \bin\ext directory along with another jar that is considered a dependency jar within the code in the jar so I hope it will reference there. The groovy code I found in Stackoverflow that should execute this jar is as follows but does not work as I don't see any output anywhere in the SoapUI directory.
Here is the code:
def command = "java -jar UpdateAppIdXMLRequest.jar file.xml"
def process = command.execute()
process.waitFor()
def output = process.in.text
log.info output
This jar creates 25 xml files that should be able to be picked up by the SoapUI and put them in as TestSteps in the same project. In my java code in what path do I put these files?
Here is the code in my jar:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
class UpdateAppIdXMLRequest {
static main(args) {
try {
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("c:\\file.xml");
Document doc = (Document) builder.build(xmlFile);
Element rootNode = doc.getRootElement();
// Create loop to create 25 testStepApps
for (int i = 1; i < 26; i++) {
// Get current AppID, incrementAppID and update the ApplicationNumber attribute value for next test script.
int appID = Integer.parseInt(rootNode.getAttributeValue("ApplicationNumber"));
appID++;
String appIDValue = Integer.toString(appID);
rootNode.getAttribute("ApplicationNumber").setValue(appIDValue);
XMLOutputter xmlOutput = new XMLOutputter();
// Create new XML file with next AppID
xmlOutput.setFormat(Format.getPrettyFormat());
xmlOutput.output(doc, new FileWriter("c:\\testStepApp" + i + ".xml"));
// xmlOutput.output(doc, System.out);
// System.out.println("File updated!");
}
} catch (IOException io) {
io.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
}
}
}
Any help/direction would be appreciated.
Thanks.
In order to do so, I recommend that you use directly groovy test step instead of a jar, this way you have more flexibility an you have not recompile the jar each time you must need to change something.
So, in order to achieve your goal, at first you need to create a TestCase inside your project, create a SOAP Test Step and Groovy Test Step inside like this:
I will use SOAP Test Step to create the other test steps (to create test steps it needs the wsdl:operation and so on, and it's more easy to copy the test step that create directly).
In the Groovy Test Step I will put the necessary code to do the work which is showed below:
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory
// read your request template
def requestFile = new File("C:/file.xml");
// parse it as xml
def requestXml = new XmlHolder(requestFile.text)
// get the current testCase to add testSteps later
def tc = testRunner.testCase;
// get the testStep as template to create the other requests
def tsTemplate = tc.getTestStepByName("Template");
// loop to create 25 testStep
for(int i = 1; i < 26; i++){
// xpath expression to get applicationNumber attribute in root node
def xpathNodeAttr = "/*/#ApplicationNumber";
// get the root node attribute applicationNumber throught an XPATH
int appId = Integer.parseInt(requestXml.getNodeValue(xpathNodeAttr));
// add 1 to appId
appId++;
// set the value again in the attribute
requestXml.setNodeValue(xpathNodeAttr,appId);
def testStepName = "TestStep_ApplicationNumber_"+ String.valueOf(appId)
log.info testStepName;
log.info testStepName.getClass().getName()
log.info tc.getClass().getName()
// create a new testStepConfig
def testStepFactory = new WsdlTestRequestStepFactory();
def testStepConfig = testStepFactory.createConfig( tsTemplate.getOperation(), testStepName )
// add the new testStep to TestCase
def newTestStep = tc.insertTestStep( testStepConfig, -1 )
// set the request which just create
newTestStep.getTestRequest().setRequestContent(requestXml.getXml())
}
This code it's basically your java code "translated" to groovy and added the necessary code to create the test steps. In a few words this code reads a request from a file, and create 25 test steps in the current test case using the request, in each request it only changes the ApplicationNumber attribute of the root node adding it +1.
EDIT BASED ON COMMENT:
If you use a REST Request step instead of SOAP Request Step you have to change a bit your groovy code to use com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory and getTestRequest() method on it. So if you have a REST Service with a POST method create a Test Case with a REST Request test step and Groovy Test Step like this:
And use this groovy code instead, basically this code it's the same and works like the code above and makes the same thing with REST Request instead of SOAP Request:
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory
// read your request template
def requestFile = new File("C:/file.xml");
// parse it as xml
def requestXml = new XmlHolder(requestFile.text)
// get the current testCase to add testSteps later
def tc = testRunner.testCase;
// get the testStep as template to create the other requests
def tsTemplate = tc.getTestStepByName("Template");
// loop to create 25 testStep
for(int i = 1; i < 26; i++){
// xpath expression to get applicationNumber attribute in root node
def xpathNodeAttr = "/*/#ApplicationNumber";
// get the root node attribute applicationNumber throught an XPATH
int appId = Integer.parseInt(requestXml.getNodeValue(xpathNodeAttr));
// add 1 to appId
appId++;
// set the value again in the attribute
requestXml.setNodeValue(xpathNodeAttr,appId);
def testStepName = "TestStep_ApplicationNumber_"+ String.valueOf(appId)
log.info testStepName;
log.info testStepName.getClass().getName()
log.info tc.getClass().getName()
// create a new testStepConfig
def testStepFactory = new RestRequestStepFactory();
def testStepConfig = testStepFactory.createConfig( tsTemplate.getTestRequest(), testStepName )
// add the new testStep to TestCase
def newTestStep = tc.insertTestStep( testStepConfig, -1 )
// set the request which just create
newTestStep.getTestRequest().setRequestContent(requestXml.getXml())
}
Hope this helps.

Resources