String c = ${__timeShift(yyyy-MM-dd,,P10D,)}
log.info("Today date " + "${c}")
vars.put("DATE_PLUS_10", "${c}")
System.out.println("${c}"); ---- This is printing 2007
def response = prev.getResponseDataAsString()
log.info('Response Initial: ' + response)
def request = response.replaceAll('""', ${DATE_PLUS_10})
log.info('Response Massaged: ' + request)
vars.put('request', request)
//vars.putObject('request', 'request');
System.out.println(${request});
I need to add 10 days to current date and replace the null value with DATE_PLUS_10
2020-02-29 20:20:15,548 ERROR o.a.j.e.JSR223PostProcessor: Problem in
JSR223 script, RESPONSE_STORE javax.script.ScriptException:
groovy.lang.MissingMethodException: No signature of method:
org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.$() is applicable
for argument types: (Script2$_run_closure1) values:
[Script2$_run_closure1#76fcaee5] Possible solutions:
is(java.lang.Object), any(), get(java.lang.String),
any(groovy.lang.Closure), use([Ljava.lang.Object;), wait() at
org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320)
~[groovy-all-2.4.13.jar:2.4.13] at
org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:72)
~[groovy-all-2.4.13.jar:2.4.13] at
javax.script.CompiledScript.eval(CompiledScript.java:92)
~[?:1.8.0_181]
Can someone pls tell me what is the issue in the line :
def request = response.replaceAll('""', ${DATE_PLUS_10})
String c = ${__timeShift(yyyy-MM-dd,,P10D,)} -
DATE_PLUS_10=2007 - this is what debug sampler displays..
Don't use ${} syntax in JSR223 script,
You can add a PreProcessor User Parameters
Allows the user to specify values for User Variables specific to individual threads
Add a variable as DATE_PLUS_10 with value:
${__timeShift(yyyy-MM-dd,,P10D,)}
Then use it in script
String c = vars.get("DATE_PLUS_10");
you can use a global or user variable and after that you can write
def DATE_PLUS_10=vars.get("DATE_PLUS_10")
log.info(DATE_PLUS_10)
def response = "2020-05-01"//prev.getResponseDataAsString()
log.info('Response Initial: ' + response)
def request = response.replaceAll('""', DATE_PLUS_10)
log.info('Response Massaged: ' + request)
As mentioned in previous answer you can not use ${} inside JSR223 processor.
I tried the below this beanshell preprocessor.
import java.text.SimpleDateFormat;
import java.util.Date;
Date date = new Date();
date.setDate(date.getDate()+10);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// or: SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy");
String formattedDate = df.format(date);
vars.put("FUTUREDATE",formattedDate);
And used the JSR post processor
def mydate =vars.get("FUTUREDATE");
log.info("my date" + mydate)
def response = prev.getResponseDataAsString()
log.info('Response Initial: ' + response)
def request = response.replaceAll('""', mydate)
log.info('Response Massaged: ' + request)
vars.put('request', request)
//vars.putObject('request', 'request');
System.out.println(${request});
Issue resolved now.
Deon't inline JMeter Functions or Variables into scripts, you can use "Parameters" section instead like:
or alternatively if you want "pure" Groovy code:
def newDate = new Date().plus(10).format('yyyy-MM-dd')
More information:
Groovy Date.plus() function
Apache Groovy - Why and How You Should Use It
Related
I am currently testing IBM MQ request using JSR223 sampler in JMeter. My scenario here is, i need to sent the request to one queue name(Queue.In) and retrieve the response from another queuename(Queue.out). Now i am able to retrieve the response from Queue.out but i am not sure it's extracting the correct message that i have sent or some other message request is in queue already(FIFO model).
May, i know how to modify my below code to send the message id/correlation id to Queue.IN and retrieve the same message id/corelation id from Queue.out or Please do suggest if there is any better approach to extract the same messages from Queue.out.
import com.ibm.mq.MQAsyncStatus
import com.ibm.mq.MQMessage
import com.ibm.mq.MQPutMessageOptions
import com.ibm.mq.MQQueueManager
import com.ibm.mq.constants.CMQC
import com.ibm.mq.constants.MQConstants
import com.ibm.mq.headers.MQRFH2
def mqProps = new Hashtable<String, Object>()
mqProps.put(MQConstants.CHANNEL_PROPERTY, 'xxxx')
mqProps.put(MQConstants.PORT_PROPERTY, 1414)
mqProps.put(MQConstants.HOST_NAME_PROPERTY, 'xxx')
def hostName = "${p_hostName}"
def hostPort = ${p_hostPort}
def channelName = "${p_channelName}"
def qManager = "${p_queueManagerName}"
def queueName = "${p_queueName}"
def qMgr = new MQQueueManager(qManager, mqProps)
def openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_INPUT_AS_Q_DEF
def queue = qMgr.accessQueue(queueName, openOptions)
def pmo = new MQPutMessageOptions()
pmo.options = MQConstants.MQPMO_ASYNC_RESPONSE
def message = new MQMessage()
message.format = CMQC.MQFMT_RF_HEADER_2
def rfh2 = new MQRFH2()
rfh2.setEncoding(CMQC.MQENC_NATIVE)
rfh2.setCodedCharSetId(CMQC.MQCCSI_INHERIT)
rfh2.setFormat(CMQC.MQFMT_STRING)
rfh2.setNameValueCCSID(1208)
rfh2.setFieldValue('usr', '${Var1}', '${Var2}')
rfh2.write(message)
message.writeString('''${request_payload}''')
queue.put(message, pmo)
queue.close()
MQAsyncStatus asyncStatus = qMgr.getAsyncStatus()
log.info('Successfully published: ' + asyncStatus.putSuccessCount + ' message(s)')
You can store the correlation id into JMeter Variables like:
vars.putObject('correlationId', message.correlationId)
where vars stands for JMeterVariables class instance, see Top 8 JMeter Java Classes You Should Be Using with Groovy article for more details.
then in order to retrieve a particular message you need to do something like:
def queueOptions = new MQGetMessageOptions()
queueOptions.options = CMQC.MQGMO_WAIT | CMQC.MQGMO_CONVERT
queueOptions.matchOptions = CMQC.MQMO_MATCH_CORREL_ID
def response = new MQMessage()
response.correlationId = vars.getObject('correlationId')
queue.get(response, queueOptions)
More information: Getting a particular message
I need to capture StartTime(Format:2021-04-28T12:09:09.000009), EndTime(Format:2021-04-28T12:09:09.000009) and test duration(milliseconds) of a JMeterLoad test.
I planning to capture StartTime(Format:2021-04-28T12:09:09.000009) in SetupThreadGroup in Jsr223Sampler and EndTime(Format:2021-04-28T12:09:09.000009) & duration in tearDownThreadGroup using below code.
---SetupThread
def now = new Date()
def starttime = now.format("yyyy-MM-dd'T'HH:mm:ss.ssssss", TimeZone.getTimeZone('UTC'))
vars.put("StartTime", starttime)
--- TearDownThreadGroup
def now = new Date()
def endtime = now.format("yyyy-MM-dd'T'HH:mm:ss.ssssss", TimeZone.getTimeZone('UTC'))
vars.put("EndTime", endtime)
def diff = vars.get("StartTime")-endtime
Getting below error
2021-04-28 18:17:11,475 ERROR o.a.j.p.j.s.JSR223Sampler: Problem in JSR223 script GetEndTime_Duration, message: javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method minus() on null object
javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method minus() on null object
You have start time saved already in variable TESTSTART.MS, you can use it in script, e.g.
long starttime = Long.valueOf(vars.get("TESTSTART.MS"))
def now = new Date()
def endtime = now.format("yyyy-MM-dd'T'HH:mm:ss.ssssss", TimeZone.getTimeZone('UTC'))
vars.put("EndTime", endtime)
def diff = now.getTime() - starttime
log.info String.valueOf(diff)
There are multiple problems with your script:
You're using vars shorthand which stands for JMeterVariables class instance and according to JMeter Documentation
Properties are not the same as variables. Variables are local to a thread; properties are common to all threads, and need to be referenced using the __P or __property function
so you should be using props instead of vars, see Top 8 JMeter Java Classes You Should Be Using with Groovy for more information on what do these shorthands mean
You're subtracting 2 strings
You're subtracting larger value (end time) from the lower value (start time)
My expectation is that in the setUp Thread Group you should use the following code:
def starttime = System.currentTimeMillis()
props.put("StartTime", starttime)
and in the tearDown Thread Group:
def endtime = System.currentTimeMillis()
def diff = endtime - props.get('StartTime')
log.info('Diff: ' + diff)
I am setting up a jmeter test plan for http requests and I want to create a table capturing some details from http request and response. I read http request from a file using CSV Data Set Config. My request and response formats are as follows
Http Request Format: {"TYPE":"<type>", "PAYLOAD": [<Array of data>]}
Http Response Format: {"RESPONSE":[<Array of data>]}
Things I want to capture for each request, response are TYPE from HTTP Request, Array Size of RESPONSE (or Array size of PAYLOAD) and Time Taken.
The jmeter version I am using is v5.2.1. Any inputs on how can I set this up?
Edit: My HTTP request is a POST request. I am looking to capture details from Request Body.
If you don't mind using JMeter Plugins you can:
Declare the variables from the CSV file as Sample Variables
Extract the number of matches from the response using JSON Extractor configured like:
Name of created variables: responsarray
JSON Path expressions: $.RESPONSE.*
Match Nr.: -1
the variable value you need to declare in the Sample Variables will be responsearray_matchNr
The above Sample Variables can be saved into a file using Flexible File Writer
If you cannot use the plugin you still can achieve the same using JSR223 Listener and the following Groovy code:
def result = new File('result.txt')
def request = new groovy.json.JsonSlurper().parseText(sampler.getArguments().getArgument(0).getValue())
def requestType = request.TYPE
def requestArray = request.PAYLOAD.size()
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def responseArray = response.RESPONSE.size()
def timeTaken = prev.getTime()
result << requestType << ',' << requestArray << ',' << responseArray << ',' << timeTaken << System.getProperty('line.separator')
I am trying to test my API response using JSON assertion in JMeter, but couldn't find out on how to achieve it. The API returns 2 values, and I need to check if the difference between these two value are consistent
API response:
{
"start": "12759898",
"end": "12759907"
}
I've tried like the above, but it seems to be wrong, as its a JSONPath variable.
Could anyone guide on how to evaluate these values? is it possible to achieve this?
It looks like a job for JSR223 Assertion
Add JSR223 Assertion as a child of the request which returns the above JSON
Put the following code into "Script" area:
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def start = response.start as long
def end = response.end as long
def delta = end - start
if (delta != 10) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Expected: 10, got: ' + delta)
}
If the difference between start and end will not be equal to 10 - the request will be marked as failed.
More information:
Groovy: Parsing and producing JSON
Scripting JMeter Assertions in Groovy - A Tutorial
In my JMeter test plan, I'm trying to write all errors out to a log. I'm using a BeanShell Post-Processor configured as follows
import org.apache.jmeter.services.FileServer;
if (ResponseCode != null && ResponseCode.equals("200") == false) {
Failure = true;
// displays in Results Tree
FailureMessage ="Creation of a new CAE record failed. Response code " + ResponseCode + "." ;
// Static elements
part1 = "Creation of a new record failed. Response code: ";
part2 = ". Sorry!";
// Open File(s)
FileOutputStream f = new FileOutputStream("d:\\error.csv", true);
PrintStream p = new PrintStream(f);
// Write data to file
p.println( part1 + ResponseCode + part2 );
// Close File(s)
p.close();
f.close();
}
I'm trying to do a simple test where the HTTP request is doing a POST that is passing in a json file from c:jmeter/tests/payloads where the directory no longer exists. (let's say someone accidentally deletes it...)
The issue is the test is stopping (see below) and never getting to the BeanShell to write the error out to a log file. I need to capture all error responses, and only error responses.
I'm not sure how to handle this. I've read Jmeter. BeanShell PostProcessor and others, but they doesn't address the issue of what happens when it doesn't get to the BeanShell.
Any help is appreciated!
org.apache.jorphan.util.JMeterStopThreadException: End of sequence
at org.apache.jmeter.functions.FileToString.execute(FileToString.java:105)
at org.apache.jmeter.engine.util.CompoundVariable.execute(CompoundVariable.java:142)
at org.apache.jmeter.engine.util.CompoundVariable.execute(CompoundVariable.java:118)
at org.apache.jmeter.testelement.property.FunctionProperty.getStringValue(FunctionProperty.java:101)
at org.apache.jmeter.testelement.AbstractTestElement.getPropertyAsString(AbstractTestElement.java:274)
at org.apache.jmeter.config.Argument.getValue(Argument.java:146)
at org.apache.jmeter.protocol.http.util.HTTPArgument.getEncodedValue(HTTPArgument.java:236)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sendPostData(HTTPHC4Impl.java:1111)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.handleMethod(HTTPHC4Impl.java:453)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:329)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1135)
at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:434)
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:261)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.FileNotFoundException: File 'C:\JMeter\test\payloads\Request_1.json' does not exist
at org.apache.commons.io.FileUtils.openInputStream(FileUtils.java:299)
at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:1711)
at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:1734)
at org.apache.jmeter.functions.FileToString.execute(FileToString.java:102)
SOLUTION
Based on Dmitri's feedback, I've switched from a Beanshell PostProcessor to Beanshell Assertion. After some tweaking, I got it to work where it now writes only errors (response != 200) to an errors.csv file. Instead of appending the file from a previous run, it overwrites with each run so only the last run's errors are captured.
If anyone thinks my solution could be improved, I'd be happy to receive the feedback. Thanks again to Kiril and Dmitri.
import org.apache.jmeter.services.FileServer;
if (ResponseCode != null && ResponseCode.equals("200") == true) {
SampleResult.setResponseOK();
}
else if (!ResponseCode.equals ("200") == true ) {
Failure = true;
FailureMessage ="Creation of a new record failed. Response code " + ResponseCode + "." ; // displays in Results Tree
print ("Creation of a new record failed: Response code " + ResponseCode + "."); // goes to stdout
log.warn("Creation of a new record failed: Response code " + ResponseCode); // this goes to the JMeter log file
// Static elements or calculations
part1 = "Unable to generate a new record via POST. The response code is: \"";
part2 = "\". \n\n For response code = \'Non-HTTP ressponse\', verify the payload file still exists. \n For response code = 409, check the recordTypeId and recordGrpId combination for validity. \n For response code = 500, verify the database and its host server are reachable. ";
// Open File(s)
FileOutputStream f = new FileOutputStream(FileServer.getFileServer().getBaseDir() + "\\error.csv");
PrintStream p = new PrintStream(f);
// Write data to file
p.println( part1 + ResponseCode + part2 );
// Close File(s)
p.close();
f.close();
}
There are no ResponseCode, Failure and FailureMessage in the Beanshell PostProcessor, switch to Beanshell Assertion instead.
Your ResponseCode.equals("200") clause assumes successful response, error responses usually have response codes > 400
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for comprehensive information on Beanshell scripting in JMeter.
Jmeter overwrites your error.csv file instead of appending to it because you reopen it on every assertion call. Try to open it beforeheand, e.g. in separate Beanshell Sampler in setup thread group:
file = new FileOutputStream("error.csv", true);
bsh.shared.custom_log = new PrintStream(file)
And then use it in your beanshell assertion in a way like:
if (ResponseCode.equals("200")==false) {
bsh.shared.custom_log.println( part1 + ResponseCode + part2 );
}
Btw, AFAIK, you didn't need this part at all, because http responses with code 200 are OK by default:
if (ResponseCode != null && ResponseCode.equals("200") == true) {
SampleResult.setResponseOK();
}
I did't tested the code so there might be typos, but very similar one works for me.
Beanshell shared values are accessed under lock, so beware of possible performance issues if you writes to it heavily. With script like this and fairly short strings (50-100 chars), i'v got ~1k writes per second without significant impact on jmeter perfomance.