Jmeter PostProcessor with Groovy and fetching content of response data - groovy

In JSR223 PostProcessor I am using this method to get the response data:
def json = new JsonSlurper().parseText(response)
Here is a snippet of my json output is like this
XmlItemResult:[[xPath:/Blocks/Block[001], name:abc, folder:\A\abc\a1, id:84, information:[[xPath:/Blocks/Block[001], result:Block number 1: abc], [xPath:/Blocks/Block[001]/Steps/CallSteps/Step[001], result:Call step StepNo 1],
folder:\Voice133, id:2542, information:[[xPath:/TestCases/TestCase[001],
This response, as you see contains two things which I am interested in:
folder:\A\abc\a1, id:84,
folder:\Voice133, id:2542,
I need to get the id value for only this line --> folder:\Voice133, id:2542,
note 2542 is variable and can be different each time and after each run.
I tried
json.find ("Voice133, id:(.+?),")

Your string is not a valid JSON, you can check it yourself using any online JSON validator, therefore you won't be able to use JsonSlurper, you will have to go for Regular Expressions instead.
In Groovy you can use =~ - Find Operator in order to be able to extract the required value(s), example code would be something like:
def response = 'XmlItemResult:[[xPath:/Blocks/Block[001], name:abc, folder:\\A\\abc\\a1, id:84,' +
' information:[[xPath:/Blocks/Block[001], result:Block number 1: abc],' +
' [xPath:/Blocks/Block[001]/Steps/CallSteps/Step[001], result:Call step StepNo 1], '
def matcher = (response =~ 'folder:\\\\A\\\\abc\\\\a1, id:(\\d+),')
if (matcher.find()) {
log.info('Folder ID = ' + matcher.group(1))
}
Demo:
More information: Apache Groovy - Why and How You Should Use It

Related

Why JMeter varibles aren't set from JSR223 Groovy Assertion?

I'm trying to set Jmeter variables extracted from Jmeter properties inside JSR223 Groovy Assertion.
Jmeter properties in which I'm interested looks like:
...
created_blob_A_6= fde65de0-3e32-11e8-a5b4-3906549016d8
created_blob_A_8= fef92d70-3e32-11e8-a5b4-3906549016d8
created_blob_A_9= ff775e20-3e32-11e8-bac3-e51250ffea15
created_blob_B_1= fd7302a0-3e32-11e8-a5b4-3906549016d8
created_blob_B_10= 00141350-3e33-11e8-bac3-e51250ffea15
...
In order to extract values from Jmeter properties, I've created JSR223 Groovy the following Assertion script:
def readParamPrefix = 'created_blob'
def writeParamPrefix = 'blob_to_delete'
def chucnkTypes = 'A'..'E'
def newBlobCounter = 1
chucnkTypes.each{ chunkLetter ->
(1..10).each{ streamNumber ->
String readParamName = readParamPrefix + '_' + chunkLetter + '_' + streamNumber
log.info('Read param name: ' + readParamName)
String writeParamName = writeParamPrefix + '_' + newBlobCounter
log.info('Write param name: ' + writeParamName)
String blob_id_to_delete = props.get(readParamName).toString().trim()
log.info('' + readParamName + ' => ' + writeParamName + ' (' + blob_id_to_delete + ')')
vars.put(writeParamName.toString(), blob_id_to_delete.toString())
newBlobCounter++
}
}
The script doesn't work for JMeter variables, but works fine for JMeter properties. Here is how JMeter properies look like:
JMeterProperties:
...
blob_to_delete_1=9b1c4f40-3e36-11e8-a5b4-3906549016d8
blob_to_delete_10=9da5e050-3e36-11e8-bac3-e51250ffea15
blob_to_delete_11=9b235420-3e36-11e8-bac3-e51250ffea15
blob_to_delete_50=9b656630-3e36-11e8-bac3-e51250ffea15
Could you tell me, how I can fix my code for setting up JMeter variables correctly?
I don't see any problem with your code:
So I would recommend:
Checking jmeter.log file for any suspicious entries
Checking what variables are defined using Debug Sampler and View Results Tree listener combination. See How to Debug your Apache JMeter Script article for more information on getting to the bottom of JMeter script failure or unexpected behavior.
Don't use ${varName} in scripts, Notice JSR223 Best Practices:
ensure the script does not use any variable using ${varName} as caching would take only first value of ${varName}. Instead use :
vars.get("varName")
You can also pass them as Parameters to the script and use them this way.
After you change it, look for errors in logs if it still doesn't works

can not pass variable to sampler's assertion in Jmeter - Groovy

I try to make a test that read from DB and assert the data
I create a JDBC request and JSR223 sampler + Jsr223 assertion.
in the sampler I created a variable called sensativity_results.
and I want to pass it to the assertion.
I used
vars.putObject("sensativity_results", sensativity_results);
and then in the assertion I try to call it and print it,
the problem is that Jmeter just not recognized the assertion,
Moreover I created another sampler called test to print the results of "sensativity_results" and Jmeter just pass it and not even execute it
int actual_sensativity ()
{
float Actual_sensativity;
int loop_num = vars.get("Loop_Number") as int;
int conversion_sense = vars.get("Conv_sens") as int;
int actual_conversion = vars.get("Conv_numbers_1") as int;
Actual_sensativity = (float) (actual_conversion/loop_num)*100;
System.out.println("************** Actual_sensativity in %: " + Actual_sensativity);
System.out.println("**conversion_sensativity: " + conversion_sense);
System.out.println("**actual_conversion: " + actual_conversion);
System.out.println("**loop number: " + loop_num);
return Actual_sensativity;
}
int sensativity_results;
sensativity_results = actual_sensativity();
vars.putObject("sensativity_results", sensativity_results);
System.out.println("sensativity_results: " + sensativity_results);
the test plan ran as expected until this step and stopped without any error it print the sensitivity results at the first sampler, and just not move on, can someone please advise?
Just put vars.put("sensativity_results", sensativity_results);
and it solved the issue
Assuming you will be using this sensativity_results variable as a String later on I would suggest storing it like:
vars.put("sensativity_results", String.valueOf(sensativity_results))
Otherwise you will get ClassCastException: java.lang.Integer cannot be cast to java.lang.String error on attempt to use it like ${sensativity_results}
Alternative way of accessing non-String variables would be using __groovy() function (available since JMeter 3.1) like:
${__groovy(String.valueOf(vars.getObject('foo')),)}

soapui free version assertions request = response

I will pass any memberid or active card for matching to verify activecard(cardno) matches memberid passed.
Request:
<MemberID>${Property Looper#memberid}</MemberID>
<CardNo>${Property Looper#ActiveCard}</CardNo>
Expected result:
<ReturnMessage>Cardno not found</ReturnMessage>
OR
<ReturnMessage>SUCCESS</ReturnMessage>
How to put assertions to check if the member id in request will check matching with response? contains and not contains assertions seems like not working that well for this condition?
and i want the test to be passed even if the matching failed as the ultimate goal is to make sure the error is not from the data (the test pass regardless the return status) but the application. Thanks
Edit:
after running the step
Edit 2:
after running script assertion
custom property added
You can use Script Assertion to achieve the same.
Based on the description, the assertion should be able to handle both below cases :
some case, you may expect card not found
some case, you may expect SUCCESS
Define test case level custom property, say EXPECTED_MESSAGE and provide appropriate expected value depending on the case.
Add below script assertion for the SOAP Request test step.
//Check if the response is received
assert context.response, 'Response is empty or null'
//Parse the response and find the ReturnMessage value
def actualMessage = new XmlSlurper().parseText(context.response).'**'.find{it.name() == 'ReturnMessage'}?.text()
log.info "Return message from response: $actualMessage"
//Read the expected message from custom property
def expectedMessage = context.expand('${#TestCase#EXPECTED_MESSAGE}')
//Verify with actual value
assert actualMessage == expectedMessage
Let us assume the output is like
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ReturnMessage>SUCCESS</ReturnMessage>
</soap:Body>
</soap:Envelope>
you can use the below script assertion
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def response = groovyUtils.getXmlHolder("First Step#Response")
String x = response.getNodeValue("//*[local-name()='ReturnMessage']")
if(x.contains("Cardno not found" ) || x.contains("SUCCESS"))
{
log.info "Success"
}
else
{
log.info " Fail"
}
output is
Sat Oct 28 15:22:02 IST 2017:INFO:Success
Rao's approach is also correct. Its just that if you are following that approach you have to have 2 expected result custom properties since you have 2 properties.
You may have to use if condition before assertion as 1 assertion will fail because your results would be either "Cardno not found" or "SUCCESS"
2 Changes you might have to make in the script. replace 'First Step' with the name of your teststep
change the getNodeValue step to reach the actual place

SoapUI Load test groovy sequentially reading txt file

I am using free version of soapui. In my load test, I want to read request field value from a text file. The file looks like following
0401108937
0401109140
0401109505
0401110330
0401111204
0401111468
0401111589
0401111729
0401111768
In load test, for each request I want to read this file sequentially. I am using the code mentioned in Unique property per SoapUI request using groovy to read the file. How can I use the values from the file in a sequential manner?
I have following test setup script to read the file
def projectDir = context.expand('${projectDir}') + File.separator
def dataFile = "usernames.txt"
try
{
File file = new File(projectDir + dataFile)
context.data = file.readLines()
context.dataCount = context.data.size
log.info " data count" + context.dataCount
context.index = 0; //index to read data array in sequence
}
catch (Exception e)
{
testRunner.fail("Failed to load " + dataFile + " from project directory.")
return
}
In my test, I have following script as test step. I want to read the current index record from array and then increment the index value
def randUserAccount = context.data.get(context.index);
context.setProperty("randUserAccount", randUserAccount)
context.index = ((int)context.index) + 1;
But with this script, I always get 2nd record of the array. The index value is not incrementing.
You defined the variable context.index to 0 and just do +1
You maybe need a loop to read all values.
something like this :
for(int i=0; i <context.data.size; i++){
context.setProperty("randUserAccount", i);
//your code
}
You can add this setup script to the setup script section for load test and access the values in the groovy script test step using:
context.LoadTestContext.index =((int)context.LoadTestContext.index)+1
This might be a late reply but I was facing the same problem for my load testing for some time. Using index as global property solved the issue for me.
Index is set as -1 initially. The below code would increment the index by 1, set the incremented value as global property and then pick the context data for that index.
<confirmationNumber>${=com.eviware.soapui.SoapUI.globalProperties.setPropertyValue( "index", (com.eviware.soapui.SoapUI.globalProperties.getPropertyValue( "index" ).toLong()+1 ).toString()); return (context.data.get( (com.eviware.soapui.SoapUI.globalProperties.getPropertyValue( "index" )).toInteger())) }</confirmationNumber>

Groovy CliBuilder: only last LongOpt is taken in account

I'm trying to use the groovy CliBuilder to parse command line options. I'm trying to use multiple long options without a short option.
I have the following processor:
def cli = new CliBuilder(usage: 'Generate.groovy [options]')
cli.with {
h longOpt: "help", "Usage information"
r longOpt: "root", args: 1, type: GString, "Root directory for code generation"
x args: 1, type: GString, "Type of processor (all, schema, beans, docs)"
_ longOpt: "dir-beans", args: 1, argName: "directory", type: GString, "Custom location for grails bean classes"
_ longOpt: "dir-orm", args: 1, argName: "directory", type: GString, "Custom location for grails domain classes"
}
options = cli.parse(args)
println "BEANS=${options.'dir-beans'}"
println "ORM=${options.'dir-orm'}"
if (options.h || options == null) {
cli.usage()
System.exit(0)
}
According to the groovy documentation I should be able to use multiple "_" values for an option when I want it to ignore the short option name and use a long option name only. According to the groovy documentation:
Another example showing long options (partial emulation of arg
processing for 'curl' command line):
def cli = new CliBuilder(usage:'curl [options] <url>')
cli._(longOpt:'basic', 'Use HTTP Basic Authentication')
cli.d(longOpt:'data', args:1, argName:'data', 'HTTP POST data')
cli.G(longOpt:'get', 'Send the -d data with a HTTP GET')
cli.q('If used as the first parameter disables .curlrc')
cli._(longOpt:'url', args:1, argName:'URL', 'Set URL to work with')
Which has the following usage message:
usage: curl [options] <url>
--basic Use HTTP Basic Authentication
-d,--data <data> HTTP POST data
-G,--get Send the -d data with a HTTP GET
-q If used as the first parameter disables .curlrc
--url <URL> Set URL to work with
This example shows a common convention. When mixing short and long
names, the short names are often one
character in size. One character
options with arguments don't require a
space between the option and the
argument, e.g. -Ddebug=true. The
example also shows the use of '_' when
no short option is applicable.
Also note that '_' was used multiple times. This is supported but
if any other shortOpt or any longOpt is repeated, then the behavior is undefined.
http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html
When I use the "_" it only accepts the last one in the list (last one encountered). Am I doing something wrong or is there a way around this issue?
Thanks.
not sure what you mean it only accepts the last one. but this should work...
def cli = new CliBuilder().with {
x 'something', args:1
_ 'something', args:1, longOpt:'dir-beans'
_ 'something', args:1, longOpt:'dir-orm'
parse "-x param --dir-beans beans --dir-orm orm".split(' ')
}
assert cli.x == 'param'
assert cli.'dir-beans' == 'beans'
assert cli.'dir-orm' == 'orm'
I learned that my original code works correctly. What is not working is the function that takes all of the options built in the with enclosure and prints a detailed usage. The function call built into CliBuilder that prints the usage is:
cli.usage()
The original code above prints the following usage line:
usage: Generate.groovy [options]
--dir-orm <directory> Custom location for grails domain classes
-h,--help Usage information
-r,--root Root directory for code generation
-x Type of processor (all, schema, beans, docs)
This usage line makes it look like I'm missing options. I made the mistake of not printing each individual item separate from this usage function call. That's what made this look like it only cared about the last _ item in the with enclosure. I added this code to prove that it was passing values:
println "BEANS=${options.'dir-beans'}"
println "ORM=${options.'dir-orm'}"
I also discovered that you must use = between a long option and it's value or it will not parse the command line options correctly (--long-option=some_value)

Resources