How to check if a value displays in particular format in XML response in soapui - groovy

I am trying to use using script assertion or by groovy code to check if a value under an element in xml response exits in particular format.
Sample response :
<ns5:price>99.99</ns5:price>
<ns5:date>2016-04-04</ns5:date>
<ns5:quantity>1</ns5:quantity>
For example, I want to check if any price exists and in format 5,4, same for date to see if date in format yyyy-mm-dd and quantity is not 0.
All the values are dynamic.
I am wondering if we can use using a script assertion or can use point and click with soap ui pro.
I am just learning soapui pro and groovy.
Thanks.

You can create an script assertion in your SOAP testStep and make the validations there. In the script assertion you can parse the response using a XmlSlurper, then get the desired nodes using findAll and perform all the asserts. You can do it using something like:
// from script assertion get the response
def response = messageExchange.getResponseContent()
// parse the XML
def xml = new XmlSlurper().parseText(response)
// get all prices
def prices = xml.'**'.findAll { it.name() == 'price' }
// check that each one has at "max 5 digits.max 4 digits"
prices.each { assert it ==~ /\d{0,5}\.\d{0,4}/ }
// get all dates
def date = xml.'**'.findAll { it.name() == 'date' }
// check the date has yyyy-MM-dd format
date.each { assert it ==~ /\d{4}\-\d{2}\-\d{2}/ }
// get all quantities
def quantity = xml.'**'.findAll { it.name() == 'quantity' }
// check that all quantities are > 0
quantity.each { assert it.text().toInteger() > 0 }
NOTE: To add an script assertion to your request, click on Assertions tab on left down corner of your SOAP Request panel:
Then right click on it and select add Assertion:
In a new panel select Script from a left side menu and then Script Assertion on the right options:
Finally use the code provided and make your checks :):

Related

How to run multiple SOAP requests from Excel spreadsheet in SoapUI?

I have a spreadsheet where each row contains a SOAP request, concatenated from the data in that row. So cell G2 is a SOAP request, cell G3 is a different SOAP request, cell G4 is another SOAP request and so on. I've looked to see what is the best method for transferring those 100+ SOAP requests into SoapUI (free version) and running them all in one batch. I've not found anything that gives me the full working solution yet. Could someone suggest the best method please? Thanks in advance!
I won't tell you how to do it, but I can tell you how I did it. Concatenating XML in Excel is messy and error-prone, especialy if you have less-technical people writing the test cases. I asked for the data (parameters) in Excel.
I wrote a Groovy script that gets the data (there's a nice script that abstracts it for you), and for each test case, saved the values as properties:
new ExcelBuilder("data/MyRegressionSheetV1.2.xls").eachLine([labels:true]) { row ->
Map payLoad = [:]
if (cell(0)) {
payLoad['MyName'] = cell(0)
payLoad['MySurname'] = cell(1)
//and so on
payLoad['ExpectedResult'] = cell(12)
testRunner.testCase.testSuite.project.setPropertyValue("Name", payLoad['MyName'])
testRunner.testCase.testSuite.project.setPropertyValue("Surname", payLoad['MySurname'])
//and so on
def MyScenario = testRunner.testCase.testSuite.testCases["SOAP Request1"].run( null, true )
then made the SOAP requests with parameterised values:
<parm:Name>${#Project#Name}</parm:Name>
<parm:Surname>${#Project#Surname}</parm:Surname>
//and so on
While in the loop, you can get the response values and if you have expected results, you can compare them programmatically:
def responseSOAP = context.expand('${SOAP Request1#Response}')
def responseSection = responseSOAP =~ /requestAnswer>(.*)<\/requestAnswer/
def response = responseSection[0][1]
if (response.equals(payLoad['ExpectedResult'])) {
testResult = 'Pass'
}
}
Opensource SoapUI is very capable, and Groovy is a very cool programming language. A lot is possible once you get your head around how they work together.
EDIT:
If you want to replace the entire request, you can access it with the XmlHolder:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
//this gets a handle on the current request XML
def oldHolder = groovyUtils.getXmlHolder( 'SOAP Request1#Request' )
//your String XML from the spreadsheet must be parsed into XML
def newHolder = new XmlSlurper().parseText(MyXMLFromSheetAsString)
//replace
context.requestContent = newHolder.xml

conditional execution of particular teststep according to result of previous request

I use SOAP UI Free.
I want to verify if previous response returns number (id) and conditionally run particular teststep.
My pseudocode below. How can I achieve this action using groovy?
How can I get response and verify if contains number and returns 200?
How can I extract this number and use it as parameter in next request
How can I compare if response is true?
response sample (200) :
523455
response sample (404) :
{
"category": "BUSINESS",
"code": "NOT_FOUND",
"description":"Account not found",
"httpStatus": 404
}
1.step GET accountId
2.step GROOVY
if(accountId is number and returns 200){
extract this number from json
run testRunner.testStep("removeAccount) for extracted number
if(response.equals("true"){
testRunner.runTestStep("createNewAccount")
}
}
1 - Use a property transfer step :
Target the id using JSONPath (should be something like "$.id")
Set "Set null on missing source" to true
Store it in a custom property of your testCase (e.g. "curId")
Additionally, if you want the Http status code, you should store it with a groovy script in another custom variable using something like this :
curHeaders = testRunner.testCase.testSteps["Get token"].testRequest.response.getResponseHeaders()
testRunner.testCase.setPropertyValue("http status", curHeaders["#status#"][0])
2 - Using a groovy script step :
Retrieve the variables above :
curId = testRunner.testCase.getPropertyValue("curId")
curHttpStatus = testRunner.testCase.getPropertyValue("http status")
Test those variables and run test step "removeAccount" if true:
if(curId && (curHttpStatus == 'HTTP/1.1 200 OK'))
{
removeActionTestStep = testRunner.testSteps["removeAccount"]
removeActionTestStep.run(null, false)
}
Note : removeAccount test step should make reference to curId custom variable (e.g. using "${#TestCase#curId}) so it runs with this id
You can add the createAccount part after the removal using jsonSlurper
removeActionResultJSON = context.expand('${removeAccount#Response}')
removeActionResultJSONSlurper = new groovy.json.JsonSlurper().parseText(removeActionResultJSON )
Then target where your response will make it equal true, then use another if - run statement like below.
Hope this helps,
Thomas

SoapUI how to get property transfer TestStep in Script Assertion of the next step

I'm using SoapUi 5.3.0 to test a case like this:
I have 3 apis: Book list, Add a book to favorite list, and Favorite list.
I add 3 apis to a TestCase as TestSteps to test the case: User views book list, choose the first book in the list then adds to favorite list, after that user goes to favorite list to verify that the book is displayed in the first place in Favorite list.
I add a propertyTransfer between step 1 and step 2, to get book_id from respond of step 1, then use to a param of the next step's request.
At step 3, I add an assertion by Script Assertion like below:
import groovy.json.JsonSlurper
//get propertyTransfer value
def tcProperty = messageExchange.modelItem.testStep.testCase.getTestStepByName("propertyTransfer").getPropertyValue("book_id")
// get response message of Favorite book api
def responseMessage = messageExchange.response.responseContent
// get book_id of the first book in favorite list
def jsonSlurper = new JsonSlurper().parseText(responseMessage)
bookId = jsonSlurper.data[0].book_id
// verify
assert bookId == tcProperty
But the script returns failed, and an error displays like attach photo
It seems tcProperty is null, means I could not get propertyTransfer value.
So where am I wrong?
You can either use Property Transfer test step or without it i.e., using Script Assertion for the request step itself.
If Script Assertion is used, then Property Transfer step is not needed at all.
The idea is extract the required value, and set it at test case level custom property in the Script Assertion.
Now, you want to use the above extracted value in the next step, which can be done using property expansion.
Here is the script assertion:
//Check if the response is not empty
assert context.response, 'Response is empty or null'
def jsonSlurper = new groovy.json.JsonSlurper().parseText(context.response)
bookId = jsonSlurper.data[0].book_id
assert bookId, 'Book id is empty or null'
//Set the bookId as test case level property
context.testCase.setPropertyValue('BOOK_ID', bookId)
In the next step, use property expansion i.e., ${#TestCase#BOOK_ID} where ever you needed book id

access response in SOAP UI in Groovy Script

I am new to Groovy Scripting. I am trying to access the value of a Response node
below is the script
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def responseHolder = groovyUtils.getXmlHolder( testRunner.testCase.testSteps["request"].testRequest.response.responseContent );
responseHolder.namespaces["ns0"]="http://xmlns.int.com/orders/xsd/v1"
String mySection = responseHolder.getNodeValue["//ns0:MT_OrderCreateDTCFulfillmentResponse/ns0:StatusCode"] ;
log.info mySection
mySection is printed as []
Response XML:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:v1="http://xmlns.int.com/orders/xsd/v1"/>
<soapenv:Body xmlns:v1="http://xmlns.int.com/orders/xsd/v1">
<ns0:MT_OrderCreateDTCFulfillmentResponse xmlns:ns0="http://xmlns.int.com/orders/xsd/v1">
<StatusCode>000</StatusCode>
<ReferenceDocNbr>NA</ReferenceDocNbr>
<SchemaValidationStatus>Validated</SchemaValidationStatus>
<StatusTimestamp>2015-08-03T18:58:01.602</StatusTimestamp>
<FaultDetails>Request for customer order number NA received successfully and format validated.</FaultDetails>
</ns0:MT_OrderCreateDTCFulfillmentResponse>
</soapenv:Body>
</soapenv:Envelope>
SOAP UI Project Structure - I am running Test_Script. Suggest me what i am missing
You've to use:
responseHolder.getNodeValue("//ns0:MT_OrderCreateDTCFulfillmentResponse/StatusCode");
instead of responseHolder.getNodeValue["//ns0:MT_OrderCreateDTCFulfillmentResponse/ns0:StatusCode"];
Note that I change responseHolder.getNodeValue invocation to use () instead of [], and also change your xpath since in your response <StatusCode> it's not defined in xmlns:ns0="http://xmlns.int.com/orders/xsd/v1".
Another option is to use the * wildcard as a namespace to map anyone. So in this case you can use:
responseHolder.getNodeValue("//*:MT_OrderCreateDTCFulfillmentResponse/*:StatusCode");
Additionally, note that probably you XML is wrong, since I suppose that all sub elements of <MT_OrderCreateDTCFulfillmentResponse> must belongs to "http://xmlns.int.com/orders/xsd/v1" namespace... so you've to declare it as:
<ns0:MT_OrderCreateDTCFulfillmentResponse xmlns:ns0="http://xmlns.int.com/orders/xsd/v1">
<ns0:StatusCode>000</ns0:StatusCode>
<ns0:ReferenceDocNbr>NA</ns0:ReferenceDocNbr>
<ns0:SchemaValidationStatus>Validated</ns0:SchemaValidationStatus>
<ns0:StatusTimestamp>2015-08-03T18:58:01.602</ns0:StatusTimestamp>
<ns0:FaultDetails>Request for customer order number NA received successfully and format validated.</ns0:FaultDetails>
</ns0:MT_OrderCreateDTCFulfillmentResponse>
Or using as default for this tag:
<MT_OrderCreateDTCFulfillmentResponse xmlns="http://xmlns.int.com/orders/xsd/v1">
<StatusCode>000</StatusCode>
<ReferenceDocNbr>NA</ReferenceDocNbr>
<SchemaValidationStatus>Validated</SchemaValidationStatus>
<StatusTimestamp>2015-08-03T18:58:01.602</StatusTimestamp>
<FaultDetails>Request for customer order number NA received successfully and format validated.</FaultDetails>
</MT_OrderCreateDTCFulfillmentResponse>
Note that if you change you XML with my indication your first XPath it's correct since now StatusCode belongs to your namespace.
Hope it helps,

How to get groovy to evaluate ${sth} when stored in string?

I'm getting a text which contains ${somethingElse} inside, but it's just a normal String.
I've got a class:
class Whatever {
def somethingElse = 5
void action(String sth) {
def test = []
test.testing = sth
assert test.testing == 5
}
}
Is it possible with groovy?
EDIT:
my scenario is: load xml file, which contains nodes with values pointing to some other values in my application. So let's say I've got shell.setVariable("current", myClass). And now, in my xml I want to be able to put ${current.someField} as a value.
The trouble is, that the value from xml is a string and I can't evaluate it easily.
I can't predict how these "values" will be created by user, I just give them ability to use few classes.
I cannot convert it when the xml file is loaded, it has to be "on demand", since I use it in specific cases and I want them to be able to use values at that moment in time, and not when xml file is loaded.
Any tips?
One thing you could do is:
class Whatever {
def somethingElse = 5
void action( String sth ) {
def result = new groovy.text.GStringTemplateEngine().with {
createTemplate( sth ).make( this.properties ).toString()
}
assert result == "Number 5"
}
}
// Pass it a String
new Whatever().action( 'Number ${somethingElse}' )
At first, what we did, was used this format in xml:
normalText#codeToExecuteOrEvaluate#normalText
and used replace closure to regexp and groovyShell.evaluate() the code.
Insane. It took a lot of time and a lot of memory.
In the end we changed the format to the original one and crated scripts for each string we wanted to be able to evaluate:
Script script = shell.parse("\""+stringToParse+"\"")
where
stringToParse = "Hello world # ${System.currentTimeMillis()}!!"
Then we were able to call script.run() as many times as we wanted and everything performed well.
It actually still does.

Resources