Inserting artificially generated XML into SOAPUI request - groovy

I am trying to do the following in SOAPUI:
Read a response and extract a node from it
Insert the node into another request
Generate some xml in a Groovy script and store in a TestCase property
Insert the generated xml from the property as a child node to the node inserted in Step 2.
For 1 and 2: The structure of the response is something like
<A><B>bb</B><C>cc</C><D>dd</D></A>
I extract it via a Property Transfer step using //A to identify the beginning of the node, and passing the node with its children to the request in the next test step. Until this, the node in the request has no content. This works.
For 3 I generate something like
<E>ee</E>
The goal after step 4 is a request structure looking like this:
<A><E>ee</E><B>bb</B><C>cc</C><D>dd</D></A>
A solution using
${#TestCase#new_xml}
to insert the node does not work because there is no way to place the property where the E node should be (as far as I know).
I tried inserting the E node via another Property Transfer test step - the value of the property gets inserted in the request as child to the A node (same way the A node was copied from the response to the next request in Step 2). The result is this:
<A><![CDATA[<E>ee</E>]]<<B>bb</B><C>cc</C><D>dd</D></A>
I would like to know:
How to insert the E node as a child node to the A node while avoiding CDATA (or removing the CDATA subsequently).
Why the xml is passed without CDATA in Step 2 which also uses the SOAPUI Property Transfer Step, but not in Step 4.
Any tips appreciated!

For 1 & 2, you can use just a simple property expansion.
Let say your Response looks like:
<AAA>
<BBB/>
<CCC/>
<BBB/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC/>
</AAA>
And let say you want to transfer the entire node DDD, including the children. In your next request you would use ${<TestStep_name>#Response//*:DDD}. Note the *: means "any namespace", since in a real SOAP Response you will probably have some kind of namespace.
For 3:
// Generate some xml in a Groovy script
def xml = '<AAA><BBB/><CCC/><BBB/><BBB/><DDD><BBB/></DDD><CCC/></AAA>'
// store in a TestCase property
testRunner.testCase.setPropertyValue('my_property', xml)
If you want to get more fancy, you could use one of the many Java XML libraries, some of which are packaged with SoapUI. Here is one possibility.
For 4, you would again use property expansion: ${#TestCase#my_property}

Related

How to parse and edit XML in TypeScript without converting to JSON

I need to repair an XML file in TypeScript and I cannot find any info on it, since everyone who posts something like this has different needs. I'd like to be pointed in the right direction here.
I have an XML request as shown below. It is autogenerated by node-soap when given JSON. Using the WSDL, node-soap attempts to fill in the namespace prefixes for each property. The problem is, it gets them wrong a lot.
In this example below, q106 should be replaced with hep3.
<soap:Envelope q15="some-good-url" q106="some-good-url-1" q98-"some-good-url-2>
...
<q98:SalesOrderAuditInfo>
<q15:ConfirmedBy xsi:nil="true"></q15:ConfirmedBy>
<q15:ConfirmedDate>0001-01-01T00:00:00</q15:ConfirmedDate>
<q15:CreatedBy>
<q106:ID>103</q106:ID>
<q106:Value>System, System</q106:Value>
</q15:CreatedBy>
<q15:CreatedDate>2022-10-26T00:43:13.413</q15:CreatedDate>
<q15:SalesOrderType>Standard</q15:SalesOrderType>
</q98:SalesOrderAuditInfo>
I know which namespace prefixes are bad because I have a sample request that was supplied to me. It's just XML. It looks like this:
<soap:Envelope hep="some-good-url" hep1="some-good-url-1" hep2-"some-good-url-2 hep3="some-good-url-3">
...
<hep2:SalesOrderAuditInfo>
<hep:ConfirmedBy xsi:nil="true"></hep:ConfirmedBy>
<hep:ConfirmedBy:ConfirmedDate>0</hep:ConfirmedByConfirmedDate>
<hep:CreatedBy>
<hep3:ID>103</hep3:ID>
<hep3:Value>System, System</hep3:Value>
</hep:CreatedBy>
<hep:CreatedDate>0</hep:CreatedDate>
<hep:SalesOrderType>Standard</hep:SalesOrderType>
</hep2:SalesOrderAuditInfo>
Here is the part that really matters. The Sample Request is the entire possible request body. The supplied request (with incorrect namespaces) is a subset of the sample request. I need to loop through each of the elements in the supplied request, and check to make sure the URL of that element matches the URL of the respective element in the sample request.
So in this example, loop through each element of supplied request. Start with SalesOrderAuditInfo. It's namespace URL is some-good-url-2. If we check the Sample Request, we can see that SalesOrderAuditInfo also corresponds to some-good-url-2.
Continue until we hit the ID tag. This has a namespace set to some-good-url-1. If we check the Same ID (inside of CreatedBy, inside of SalesOrderAuditInfo), we can see the namespace should actually be set to some-good-url-3. So we replace q106 with hep3.
I also need to take all of the namespaces defined in the Sample Request Envelope and move them into the supplied request envelope so that this new hep3 will be defined.
At this point, I need to edit the namespace prefix. In this example, q106:ID would be replaced be the string hep3:ID. Same with all of the closing tags.
Which library can I use to accomplish this in XML? Is anyone familiar with node-soap screwing these namespaces up and know of any fix?
I am using node-soap v0.43

SOAP UI how to configure a PUT request body programmatically

I'm configuring some requests programmatically in my test cases, I can set headers, custom properties, teardown scripts, etc. however I can't find how to set a standard json body for my put requests.
Is there any possibility from the restMethod class ?
So far I end up getting the method used :
restService = testRunner.testCase.testSuite.project.getInterfaceAt(0)
resource = restService.getOperationByName(resource_name)
request = resource.getRequestAt(0)
httpMethod = request.getMethod()
if (httpMethod.toString().equals("PUT"))
but then I'm stuck trying to find how to set a standard body for my PUT requests.
I try with the getRequestParts() method but it didn't give me what I expected ...
can anyone help, please
thank you
Alexandre
I’ve managed this. I had a tests of tests where I wanted to squirt the content of interest into the “bare bones” request. Idea being that I can wrap this in a data driven test. Then, for each row in my data spreadsheet I pull in the request body for my test. At first I simply pulled the request from a data source value in my spreadsheet, but this became unmanageable in my spreadsheet.
So, another tactic. In my test data sheet (data source) I stored the file name that contains the payload I want to squirt in.
In the test itself, I put in a groovy step immediately before the the step I want to push the payload into.
The groovy script uses the data source to firstly get the file name containing the payload, I then read the contents of the file.
In the step I want to push the data into, I just use a get from data, e.g. {groovyStep#result}.
If this doesn’t completely make sense, let me know and I’ll update with screenshot when I have access to SoapUi.

How to record the timestamp of an XML request in SoapUI and use it in an assertion?

I have a test case in SoapUI NG Pro which has the following steps:
POST REST Request that starts a process
JDBC Request where I check that the process Start Date has been logged to a database table
Delay (to simulate the time it takes for the process to run)
JDBC Request where I check that the End Date and Duration have been logged to the table
I would like to capture the timestamp of the POST Request to use within my assertions in steps 2 and 4.
I have looked around online and some people have mentioned using Events while others have mentioned using a Script TestStep but I haven't been able to get either to work.
I can get the POST Response timestamp but am looking for the Request timestamp in particular. I also noticed that there is a timestamp in the Request Log but again I don't know how to access that.
Any help would be greatly appreciated. Its probably also worth mentioning that I am using JavaScript instead of Groovy.
You can add a Script Assertion for the Soap Request test step and add the below statement in order to show the time taken.
log.info messageExchange.response.timeTaken
If you want the above value to be accessible in other steps, then use below(which stores the value to test case level, so that it is easy to access the test case property in other steps of the same test case):
context.testCase.setPropertyValue('TIME_TAKEN', messageExchange.response.timeTaken.toString())
In the later steps, use Property Expansion to read the test case level property value
def timeTaken = context.expand('${#TestCase#TIME_TAKEN}') as Integer

How to use nested paramter in SoapUI context.expand expression?

My use case is that I want to do a bulk update of request bodies in multiple SoapUI projects.
Example of request body.
{
"name": "${#TestSuite#NameProperty}"
"id": "${#TestSuite#IdProperty}"
}
I want to expand the property ${#TestSuite#NameProperty} through Groovy, and get the value stored at TestSuite level then modify it as necessary.
Suppose I have 50 test steps in my test case and I want to expand the request for each one from Groovy script. To expand a specific test steps, I would pass the test Steps's name. For example:
expandedProperty = context.expand('${testStep1#Request}')
But, how can I achieve the same, if I wanted to iterate over all 50 test steps? I tried to used a nested parameter inside the context.expand expression, but it did not work. For Example:
currentTestStepName = "TestStep1"
expandedProperty = context.expand('${${currentTestStepName}#Request}')
This only returned me the expanded request from the test step right above it (where I am running the groovy script from) rather than the "TestStep1" step. ( Which is madness!)
Also, context.expand only seems to work while executing via Groovy script from the SoapUI workspace project. Is there and other way, or method similar to context.expand which can expand the properties like "${#TestSuite#NameProperty}" during headless execution? Eg: A groovy compiled jar file imported in SoapUI.
Thanks for any help in advance!
You can use context.expand('${${currentTestStepName}#Request}') way to get it.
There are other approaches as well, which does not use context.expand.
In order to get single test step request of any given test step:
Here user passes step name to the variable stepName.
log.info context.testCase.testSteps[stepName].getPropertyValue('Request')
If you want to get all the requests of the test case, here is the simple way using the below script.
/**
* This script loops thru the tests steps of SOAP Request steps,
* Adds the step name, and request to a map.
* So, that one can query the map to get the request using step name any time later.
*/
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
def requestsMap = [:]
context.testCase.testStepList.each { step ->
log.info "Looking into soap request step: ${step.name}"
if (step instanceof WsdlTestRequestStep) {
log.info "Found a request step of required type "
requestsMap[step.name] = context.expand(step.getPropertyValue('Request'))
}
}
log.info requestsMap['TestStep1']
Update :
If the step that you are interested is REST step, use below condition instead of WsdlTestRequestStep in the above.
if (step instanceof com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep) { //do the stuff }

Test JSF application on multiple servers with same JMeter test script

At the moment we are developing an application and deploying it in my local machine. And now I'm doing a load test using jmeter and it runs without a issue. The problem I'm getting is when I try to run the same test on a different machine with a different server it doesn't work.
And I observed that html element id's are different on different servers with JSF.(Issue is form submissions are not working). Is there a way to overcome this issue with jmeter since I want to run the same test scripts on different servers.
The process of extracting dynamic values from previous response and adding them to next request is called correlation. JMeter provides variety of Pre Processors and Post Processors to allow modification of requests on-the-fly.
Example use case:
Send a GET request a JSP page which contains a number of inputs
Extract all the inputs names and populate values where required
Populate dynamic fields of next request with values extracted in point 2
Send a POST request
Point 1: No changes to your script required
Point 2:
Add XPath Extractor as a child of GET Request and populate it as follows:
Reference Name: INPUT
XPath Query: //input/#name | //input[#type='hidden']
This extractor will fetch all <input> HTML elements and store it to JMeter Variables as
INPUT_1=javax.faces.ViewState
INPUT_2=loginForm_SUBMIT
INPUT3=...
...
Add a Beanshell Pre Processor as a child of next request with the following code
import java.util.Iterator;
import java.util.Map;
Iterator iter = vars.getIterator();
while (iter.hasNext())
{
Map.Entry e = (Map.Entry)iter.next();
if (e.getValue() != null)
{
if (e.getKey().toString().startsWith("INPUT_") && e.getValue().toString().length() >0)
{
sampler.addArgument(e.getValue().toString(),"VALUE OF YOUR INPUT");
}
}
}
The code above will fetch all variables prefixed with INPUT_ and add it as parameters to your next request.
See How to use BeanShell: JMeter's favorite built-in component guide for more information on Beanshell scripting in Apache JMeter to see what else can be done using Beanshell scripting and using of JMeter objects exposed to Beanshell test elements.

Resources