Groovy script to validate ResponseData in JMeter - groovy

I have written this script to verify field types, but i'm not sure if it is being validated correctly. Also i want to verify all the expected fields are seen.
This is my BSF Assertion:
import groovy.json.*;
def response = prev.getResponseDataAsString();
def json = new JsonSlurper().parseText(response)
def eventName = json.event_name
(eventName.getClass() == String)
def eventDate = json.event_start
(eventDate.getClass() == Date)
def attendeeLimit = json.attendee_limit
(attendeeLimit.getClass() == Integer)
def orderCount = json.order_count
(orderCount.getClass() == Integer)
def attendanceLimit = json.attendance_limit_on
(attendanceLimit.getClass() == String)

If you want to check JSON response data types change your lines like
(eventName.getClass() == String)
to
assert eventName instanceof String
See Groovy Testing Guide for details
I would suggest switching fro BSF Assertion to JSR223 Assertion as it is able to compile the script and cache hence your script will perform much better. See Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! article for comprehensive explanation and scripting best practices.
There is also a JSON Path Assertion available via JMeter Plugins, this one is mainly used to check response content

Related

Vars.get returns a null value

def signValue = '${signature_value}.${timestamp}.${signature_value}'
def token_secret = '${APP_CLIENT_SECRET}'
log.info("token is " + signValue)
def signingKey = new javax.crypto.spec.SecretKeySpec(signValue.getBytes(),"HmacSHA256");
def mac = javax.crypto.Mac.getInstance("HmacSHA256")
mac.init(signingKey);
def hmac = mac.doFinal(token_secret.getBytes());
def result = hmac.encodeBase64().toString()
---- I want to use the above "result" variable into a Http sampler request body------
---- I tried many possible ways but I end up is getting value as null or some error--
//${__groovy(vars.get("result"))}
//vars.put("signature", vars.get(result))
I've been trying to extract the value of the variable "result" and use it in HTTP sampler results. But I ended up getting a null value or some other error. Anyone could help me to sort out this problem.
Thanks!
I don't get the point, result should be a String object, is it not what you are expecting to have?
Anyway, signValue and token_secret perhaps could be different from your expectations: using single quotes instead of double quotes you are not using GStrings (e.g. the value of token_secret will be always exactly '${APP_CLIENT_SECRET}', regardless of the value of APP_CLIENT_SECRET)
Change this line:
vars.put("signature", vars.get(result))
to this:
vars.put("signature", result)
Also don't inline JMeter variables into Groovy scripts like this:
def token_secret = '${APP_CLIENT_SECRET}'
use vars shorthand instead:
def token_secret = vars.get('APP_CLIENT_SECRET')
Because:
It conflicts with Groovy GStrings
For best performance it's recommended to cache compiled scripts (enabled by default)
and in this mode JMeter resolves only first value and caches it which means you will get the same value for every iteration
More information:
JSR223 Sampler Documentation
Apache Groovy - Why and How You Should Use It
Put vars the result:
vars.put("signature", hmac.encodeBase64().toString());
And in HTTP use ${signature}

Access test case property from test suite tear down script

I am trying to access the test case property from test suite tear down script.
i am not able to use test runner properties.
def testSuiteProperty = testRunner.testCase.testSuite.getPropertyValue( "MyProp" )
Need to access the test case property using test case name.
It will be very helpful if some one can answer it.
To access the test Suite property, it is simply a case of this in your tear down script....
def someProp = context.expand( '${#TestSuite#someProp}' )
Now, I use the Pro version and I don't know what you're using, so I'm not sure if the next part of my answer will help.
In Setup Script, Tear Down script, Script assertions, you can 'right-click' in the code window where you type your script and there is a 'Get Data' menu item int he context menu. This allows you to select a piece of data of interest. In fact, the line of code above was generate by using the 'Get Data' context menu option.
To access a custom property for a given test case within your suite tear-down script, you need to do this...
def testCase = testSuite.testCaseList.find { p -> p.name == 'TestCase 2' }
def testProp = testCase.getProperty('testCaseProp');
log.info(testProp.value);
The syntax you are using is not correct
Try using this
def testCs = testRunner.testCase.testSuite.project.testSuites["name of testsuite"].getTestCaseByName(name)
def tcprop = testCs.getPropertyValue("NameOftestCaseProp")
We are first getting refernce of the test case and then accessing its property
or below should also work
def testcaseProp= testRunner.testCase.testSuite.project.testSuites["name of testsuite"].getTestCaseByName(name).getPropertyValue("name of property)
try whichever looks simple to you, though both are same

Run a test step in Script assertion SOAP UI

I have 5 test steps in a test case and i want to write a script assertion for a test step
Like
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def httpResponseHeaders = context.testCase.testSteps["Step1"].testRequest.response.responseHeaders
def httpStatus = httpResponseHeaders["#status#"]
def httpStatusCode = (httpStatus =~ "[1-5]\\d\\d")[0]
if (httpscode == "500")
I want to re-run the test step named as step 1
I know that testRunner class is not present in Script assertion is there a way to do it with messageExchange variable class
I saw an answer on stack overflow
`messageExchange.modelItem.testStep.testCase.getTestStepByName("Step1").run(context.getTestRunner(),context)`
I tried the code but as soon as i click run SOAP UI hangs and I have to force close the SOAP UI application
To run a test step from script assertion you may use this
import com.eviware.soapui.support.types.StringToObjectMap
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner
def Runner = new WsdlTestCaseRunner(messageExchange.modelItem.testStep.testCase, new StringToObjectMap())
yourTestStep= messageExchange.modelItem.testStep.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Library"].testSteps["Lib"]
yourTestStep.run(Runner,context)
Your code is fine, except your logic is flawed, because you encounter the error 500 for the first time and then you call the same step again and it fails again with 500 and so on. You would need to get different status, before your Java runs out of memory.
So if you want to do something like that, you have to implement some kind of counter (using TestCase, TestSuite, Project or Global property) to perform this loop only several times and then fail.
Anyway this worked for me:
def utilitiesSuite = messageExchange.modelItem.testStep.testCase
.testSuite.project.getPropertyValue('utilitiesTestSuiteName');
messageExchange.modelItem.testStep.testCase.testSuite.project
.testSuites[utilitiesSuite].testCases["Test Case utility name"]
.run(null, true);
In this case we have all "utilities" = test cases with some often needed functionality in a dedicated test suite and I wanted its name to be possible to set up on Project level, of coures the Test Suite name can be put there directly as for example "Utilities'.
Also i have tried with this:
context.getTestRunner()
As the first parameter in the methor run instead of the null, but it worked only when testing the one requirement, not when running whole test case or test suite.
I let here another example that worked for me.
It's an assertion script, which runs a testStep basing on a response node value.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context );
def holder = groovyUtils.getXmlHolder( "yourTestStep#response" );
def myValue = holder.getNodeValue( "//theNameSpace:yourNode" );
if(myValue == 'whateverYouWant'){
//com.eviware.soapui.support.UISupport.showInfoMessage(myValue);
def Runner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(
messageExchange.modelItem.testStep.testCase, new com.eviware.soapui.support.types.StringToObjectMap());
def mySteps= messageExchange.modelItem.testStep.testCase.testSuite.project.testSuites["yourTestSuite"].testCases["yourTestCase"].testSteps["yourTestStep"];
mySteps.run(Runner,context);
}

Is there a way to declare a Groovy string format in a variable?

I currently have a fixed format for an asset management code, which uses the Groovy string format using the dollar sign:
def code = "ITN${departmentNumber}${randomString}"
Which will generate a code that looks like:
ITN120AHKXNMUHKL
However, I have a new requirement that the code format must be customizable. I'd like to expose this functionality by allowing the user to set a custom format string such as:
OCP${departmentNumber}XI${randomString}
PAN-${randomString}
Which will output:
OCP125XIBQHNKLAPICH
PAN-XJKLBPPJKLXHNJ
Which Groovy will then interpret and replace with the appropriate variable value. Is this possible, or do I have to manually parse the placeholders and manually do the string.replace?
I believe that GString lazy evaluation fits the bill:
deptNum = "C001"
randomStr = "wot"
def code = "ITN${deptNum}${->randomStr}"
assert code == "ITNC001wot"
randomStr = "qwop"
assert code == "ITNC001qwop"
I think the original poster wants to use a variable as the format string. The answer to this is that string interpolation only works if the format is a string literal. It seems it has to be translated to more low level String.format code at compile time. I ended up using sprintf
baseUrl is a String containing http://example.com/foo/%s/%s loaded from property file
def operation = "tickle"
def target = "dog"
def url = sprintf(baseUrl, operation, target)
url
===> http://example.com/foo/tickle/dog
I believe in this case you do not need to use lazy evaluation of GString, the normal String.format() of java would do the trick:
def format = 'ITN%sX%s'
def code = { def departmentNumber, def randomString -> String.format(format, departmentNumber, randomString) }
assert code('120AHK', 'NMUHKL') == 'ITN120AHKXNMUHKL'
format = 'OCP%sXI%s'
assert code('120AHK', 'NMUHKL') == 'OCP120AHKXINMUHKL'
Hope this helps.
for Triple double quoted string
def password = "30+"
def authRequestBody = """
<dto:authTokenRequestDto xmlns:dto="dto.client.auth.soft.com">
<login>support#soft.com</login>
<password>${password}</password>
</dto:authTokenRequestDto>
"""

Find an element in XML using XML Slurper

"I have a code that is working as expected but now I have to find the element in different format. Example is below
<car-load>
<car-model model="i10">
<model-year>
<year.make>
<name>corolla</name>
</year.make>
</model-year>
</car-model>
</car-load>
I have to find the value of "corolla" from this XML. Please reply.
You can run this in the Groovy console
def text = '''
<car-load>
<car-model model="i10">
<model-year>
<year.make>
<name>corolla</name>
</year.make>
</model-year>
</car-model>
</car-load>'''
def records = new XmlSlurper().parseText(text)
// a quick and dirty solution
assert 'corolla' == records.toString()
// a more verbose, but more robust solution that specifies the complete path
// to the node of interest
assert 'corolla' == records.'car-model'.'model-year'.'year.make'.name.text()

Resources