how to write all Soap Request available in Project using Soap UI Groovy - 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"
}
}
}
}

Related

Automatic Data Driven tests in SoapUI via Groovy Script

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?

Copy attachement of a Soap Request into TestStep request

I'm copying Soap Request of a project into a testCase with a load script (project level), it all went good, unless I discover that all attachment files were not copied.
Here's my script :
testsuite=project.addNewTestSuite("Suite")
testcase=testsuite.addNewTestCase("Case")
def iface= project.interfaces["Interface"]
def op = iface.operations["Operation"]
op.getRequestList().each { req ->
def config=com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory.createConfig(req, req.getName())
def newTestStep = testcase.addTestStep( config );
}
Is there a way to copy every request's attachment into it's testStep copy?
If I need to add manually my test suite, and use a setup script (to use context, runner ...) I'm ready to do that.
Thanks
You've to get all attachments from the request in your operation list and import each one in the new TestStep, something like this must works for your case:
req.attachments.each{ attach ->
newTestStep.testRequest.importAttachment(attach)
}
All together in your code:
def project = testRunner.testCase.testSuite.project
def testsuite= project.addNewTestSuite("Suite")
def testcase= testsuite.addNewTestCase("Case")
def iface= project.interfaces["Interface"]
def op = iface.operations["Operation"]
op.getRequestList().each { req ->
def config=com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory.createConfig(req, req.getName())
def newTestStep = testcase.addTestStep( config )
req.attachments.each{ attach ->
newTestStep.testRequest.importAttachment(attach)
}
}

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)

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.

soapui shared datasource in groovy script

I have prepared a test case in SoapUI Open Source which loops over values in csv file and sends request for each set of values (taken care of by groovy script). I want to modify it so each thread for each new iteration uses value from next row of csv file.
import com.eviware.soapui.impl.wsdl.teststeps.*
def testDataSet = []
def fileName = "C:\\sSHhrTqA5OH55qy.csv"
new File(fileName).eachLine { line -> testDataSet.add( line.split(",") ) }
def myProps = new java.util.Properties();
myProps = testRunner.testCase.getTestStepByName("Properties");
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase;
def testStep = testCase.getTestStepByName("TestRequest");
testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
while (true) {
for ( i in testDataSet ) {
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
}
I want to modify this script so each thread from the pool gets unique (next) unused value from data source
I tried to use newFixedThreadPool from java.util.concurrent as suggested here (Concurrency with Groovy), however I can't get it to work - either requests are duplicated or SoapUI crashes (I am new to concurrency).
Can you please help me to get it right?
I think this would work for you:
while (true) {
for ( i in testDataSet ) {
def th = Thread.start(){
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
th.join()
}
So, new threads would be created on each loop.
If you wanted to test out if its working you could place loginfo(s) in the code...
log.info("Thread Id: " + Thread.currentThread().getId() as String)
I don't see your point. SoapUi already gives you a datasource test step that accepts a csv file as input.
So once you have all these values you can transfer the properties and run the test.

Resources