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)
}
}
Related
I'm trying to create a simple groovy script that will download some JSON from a website, pretty print it, and then save it to a file. I'm using this as an exercise to learn how to practice some functional concepts and I'm running into an issue I can't figure out. Basically, the last composed closure has multiple params and I can't figure out how to apply it. I'd like the end result to be a one liner that specifies the URL and file location to save the contents.
def getJson = { sourceUrl ->
def conn = new URL(sourceUrl).openConnection() as HttpURLConnection
return conn.inputStream.text
}
def prettyPrintJson = { json ->
return groovy.json.JsonOutput.prettyPrint(json)
}
def save = { data, fileLocation ->
new File(fileLocation).write(data)
}
def sync = getJson >> prettyPrintJson >> save
sync('https://jsonplaceholder.typicode.com/posts') // don't know how to specify the fileLocation
If you compose functions, your innermost function determines the
arguments. So you could provide the second argument to save via
rcurry. E.g.:
def sync = getJson >> prettyPrintJson >> save.rcurry("/tmp/out.json")
sync('https://jsonplaceholder.typicode.com/posts')
Or you would have to thread the second argument down the line until you
need it. E.g.:
def getJson = { sourceUrl, out ->
[sourceUrl.toURL().text, out]
}
def prettyPrintJson = { json, out ->
[groovy.json.JsonOutput.prettyPrint(json), out]
}
def save = { data, fileLocation ->
new File(fileLocation).write(data)
}
def sync = getJson >> prettyPrintJson >> save
sync('https://jsonplaceholder.typicode.com/posts', '/tmp/out.json')
I'd imagine, that by using a macro (since 2.5) there should be a chance to
create a threading macro (e.g. like in Clojure).
I have a testSuite with lets say 5 cases, i run the cases from my testSuite.
In my tear down script I want to capture all request and response of all testcases all test testSteps.
Below is the code I have written in tearDown TestSuite, problem in context.expand is returning empty. I assume testCase context is require, or not sure where i am going wrong.
tc_list = testSuite.getTestCaseList()
tc_count = tc_list.size()
for(i=0;i<tc_list.size();i++){
if(!tc_list[i].isDisabled()){
ts_list = tc_list[i].getTestStepList()
for(j=0;j<ts_list.size();j++){
req = testSuite.getPropertyValue("reportpath")+'/'+testSuite.getName()+'/'+tc_list[i].getName()+'/'+ts_list[j].getName()+'_RequestData.txt'
res = testSuite.getPropertyValue("reportpath")+'/'+testSuite.getName()+'/'+tc_list[i].getName()+'/'+ts_list[j].getName()+'_ResponseData.txt'
def request_expand = context.expand('${'+ts_list[j].getName()+'#Request}')
log.info '${'+ts_list[j].getName()+'#Response}'+tc_list[i].getName()
def response_expand = context.expand('${'+ts_list[j].getName()+'#Response}')
log.info response_expand
/* def req_file = new File(req)
req_file.write(request_expand,"UTF-8")
def res_file = new File(res)
res_file.write(response_expand,"UTF-8") */
}
}
}
#Ragesh kr
Whenever any time in Soap ui or Ready API you need RawRequest or RawResponse
you can just replace Request with RawRequest
and Response with RawResponse
i just did in your code and it worked
def request_expand = testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getPropertyValue("RawRequest")
def response_expand = testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getPropertyValue("RawResponse")
Some other examples to help everyone
When we just need request and response in soapui we can use below
When we just need RawRequest and RawResponse in soapui/ReadyaPI via groovy we can use below
req=context.expand('${RequestStepName#RawRequest}')
log.info req
res=context.expand('${RequestStepName#RawResponse}')
log.info res
The Below code worked for me. But I am still trying to capture rawRequest and rawResponse, which is still not achieved
tc_list = testSuite.getTestCaseList()
tc_count = tc_list.size()
for(i=0;i<tc_list.size();i++){
if(!tc_list[i].isDisabled()){
ts_list = tc_list[i].getTestStepList()
for(j=0;j<ts_list.size();j++){
req = testSuite.getPropertyValue("reportpath")+'/'+testSuite.getName()+'/'+tc_list[i].getName()+'/'+ts_list[j].getName()+'_RequestData.txt'
res = testSuite.getPropertyValue("reportpath")+'/'+testSuite.getName()+'/'+tc_list[i].getName()+'/'+ts_list[j].getName()+'_ResponseData.txt'
def request_expand = testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getPropertyValue("Request")
def response_expand = testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getPropertyValue("Response")
def req_file = new File(req)
def res_file = new File(res)
log.info testSuite.getTestCaseByName(tc_list[i].getName()).getName()+' '+testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getName()+' '+response_expand
if(request_expand!=null && response_expand!=null){
log.info testSuite.getTestCaseByName(tc_list[i].getName()).getName()+' '+testSuite.getTestCaseByName(tc_list[i].getName()).getTestStepByName(ts_list[j].getName()).getName()+' '+response_expand
req_file.write(request_expand,"UTF-8")
res_file.write(response_expand,"UTF-8")
}
}
}
}
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"
}
}
}
}
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.
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.