${__time} function output is incorrect - jmeter

I'm trying to get today's date using time function of jmeter with the format "${__time(yyyy-MM-dd)}" in BeanShell postprocessor. But after executing the Beanshell postprocessor the result shows as "1996". Basically the "time" function is displaying result by subtracting the values like "2018-03-19"=1996.
Please help me to resolve this issue so that i can get current date and time.
Beanshell code as below
import org.apache.jmeter.gui.GuiPackage;
import org.apache.commons.io.FilenameUtils;
String testPlanFile = GuiPackage.getInstance().getTestPlanFile();
String testPlanFileDir = FilenameUtils.getFullPathNoEndSeparator(testPlanFile);
vars.put("testPlanFileDir", testPlanFileDir);
//create the file in test plan file dir and print current time and Date
FileOutputStream f = new FileOutputStream(testPlanFileDir+"/CurrentDate.txt", true);
PrintStream p = new PrintStream(f);
this.interpreter.setOut(p);
//current date and time;
print("Current date is:"+${__time(yyyy-MM-dd)});
f.close();

Set time function call as parameter of your PreProcessor (by the way migrate to JSR223 + Groovy for performances)
And use it then with variable Parameters:

Try this with JSR223 PostProcessor and language Groovy and put this into script area:
def a = new Date().format('yyyy-MM-dd')
new File('Example.txt').withWriter('utf-8') {
writer -> writer.writeLine 'Current date is : ' + a.toString() }
(It works on JMeter 4.0)

You should move to JSR223 postprocessor according to JMeter Best Practices:
Since JMeter 3.1, we advise switching from BeanShell to JSR223 Test Elements
Until then you can fix it by quoting the function call as
print("Current date is:"+"${__time(yyyy-MM-dd)})";
This fix will treat the function's return value as string.
Currenty it treat it as a numeric substraction: 2018-3-19=1996 and then convert it to string

Performance anti-pattern #1: given you use GuiPackage class you won't be able to execute your test in non-GUI mode, consider migrating to FileServer instead
Performance anti-pattern #2: using Beanshell is not recommended as in case of high loads it might become the bottleneck. Since JMeter 3.1 it is recommended to use JSR223 Test Elements and Groovy language for any form of scripting
Performance anti-pattern #3: don't inline JMeter Variables or Functions in script body they break Groovy compiled scripts caching function and might resolve into something which will cause unexpected behaviour (like in your case), compilation failure or even data loss.
So:
Add JSR223 PostProcessor instead of the Beanshell one
Put the following code into "Script" area:
String testPlanDir = org.apache.jmeter.services.FileServer.getFileServer().getBaseDir()
File currentDate = new File(testPlanDir + File.separator + "CurrentDate.txt")
currentDate << new Date().format("yyyy-MM-dd")

Related

Jmeter beanshell sampler writing multiple lines

In my JMeter(5.1.1) script, I am trying to write into a csv file using BeanShell PostProcessor.
Where beanshell code is,
var name = "name";
var email = "email";
var currtime = "${__time(d-MMM-yyyy hh:mm:ss)}";
f = new FileOutputStream("D:/Temp/Temp.csv", true);
p = new PrintStream(f);
this.interpreter.setOut(p);
print(currtime + "," + name + "," + email);
p.close();
f.close();
It works but writes 3 lines in Temp.csv.
15-Nov-2020 05:16:32,name,email
15-Nov-2020 05:16:33,name,email
15-Nov-2020 05:16:34,name,email
Where only one line is expected to be written in CSV. Please suggest how to fix this error.
Your Beanshell PostProcessor is located on Thread Group level, it means that it's being run after every Sampler in its scope
If you want it to be executed after a certain Sampler - move the PostProcessor to be the child of this sampler
2.Since JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language for scripting.
If you run your test with >1 thread (virtual user) each user will be writing the lines into the same file and in case of concurrent writing you will face data corruption and/or loss due to the race condition so I would recommend considering switching to Flexible File Writer instead.

Calling JSR223 Pre processor for each request

I am using JSR223 Pre processor to generate UUID in http header. The value will be updated in a log file with timestamp for tracking purpose.
I have added the pre processor in each call, so every time it generates an unique value and updates the log file. Please have a look on below code.
import org.apache.jmeter.services.FileServer;
import java.sql.Timestamp;
import java.util.UUID;
String uuid = UUID.randomUUID().toString();
vars.put("p_x_transaction_id",uuid);
uid= vars.get("p_x_transaction_id");
String Logfile=vars.get("p_logfile");
f = new FileOutputStream(Logfile,true);
p = new PrintStream(f);
this.interpreter.setOut(p);
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
p.println(timestamp + " - " + uid);
Is it possible put above code in JSR223 sampler and call the method in header directly?
I have tried but it generates unique value for each iteration only.
Please throw some lights on this.
There is no need to copy and paste the JSR223 PreProcessor and add it to each call, the JSR223 PreProcessor obeys JMeter Scoping Rules so if you put it at the same level as all your Samplers - it will be applied to all the Samplers
As you can see I have only one instance of the JSR223 PreProcessor and it has been executed 3 times (before each Sampler in its scope)

Cann't execute my test if I add __intSum function to the beanshell postprocessor

I have written a regular expression (regexpname) in my thread which returns a number Ex: 10 and when I try to use the regular expression in the BeanShell postprocessor by adding __intSum function to add a number to the regular expression out put Ex: to add 4 to the regular expression out put i.e., 10 and store the result to a variable Ex: Total, using the following function:
{__intSum(4,${regexpname},Total}
upon trying to run my test, it stops immediately with the message
"Jmeter: Uncaught exception: java.lang.NumberFormatException: For
input string: "${regexpname}".....".
Please let me know how to fix the issue:
Here is the code I have put in beanshell postprocessor:
import java.text.SimpleDateFormat;
SimpleDateFormat sdf = new SimpleDateFormat("m/dd/yyyy"); // change it according to your Date format
Date originalDate = sdf.parse(vars.get("SigDate"));
Calendar cal = Calendar.getInstance();
cal.setTime(originalDate);
${__intSum(4,${regexpname},Total)};
cal.add(Calendar.DAY_OF_YEAR, Total); // change it if you need to add something else
Date newDate = cal.getTime();
vars.put("newDepdate", sdf.format(newDate));
log.info("Original date: " + vars.get("SigDate"));
log.info("New date: " + vars.get("newDepdate"));
Don't inline JMeter Functions and/or variables into scripts as they can resolve into something which will cause script failure or inconsistent behaviour. Either use "Parameters" section or go for code-based equivalents
Don't use Beanshell test elements, it is recommended to switch to JSR223 Test Elements and Groovy language for any form of scripting since JMeter 3.1
Your date format looks flaky as m stands for "minutes in hour", if you need "month in year" - go for capital M
Actually you don't even need any scripting here as there is __timeShift() function since JMeter 3.2 which can do what you need, the relevant syntax would be something like:
Use int Total = Integer.parseInt(vars.get("regexpname"))+4; instead of ${__intSum(4,${regexpname},Total)}; in your beanshell pre processor
I have defined regexpname as 10 in test plan so its adding 14 days and storing new date in newDepdate.
For more information on beanshell please follow this link
Please let me know if it helps..

Jmeter: Comparison of multiple result for result response with JDBC variables

In j meter: In a bean-shell assertion or any other I want to match the content of response which I have fetched using Jason extractor suppose:
Result[1]=A, Result[2]=b, Result[3]=c
and so on Versus variables I have fetched using JDBC pre-processor which has saved as:
Result_1=, Result_2=B, Result_3=c.
I am able to match 1 variable at a time but not all at one time. so need help with bean-shell code to compare all result at once.
Add JSR223 Assertion somewhere to your test plan (normally as a child of a Sampler you would like to fail)
Put the following code into "Script" area
for (int i = 1; i <= Integer.parseInt(vars.get('ResultFromJSON_matchNr')); i++) {
if (!vars.get('ResultFromJSON' + i).equals(vars.get('ResultFromJDBC_' + i))) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Variables mismatch')
}
}
Make sure you have groovy selected as the "Language" and have Cache compiled script if available box ticked
The above script assumes ResultFromJSON and ResultFromJDBC JMeter Variables reference names, amend them according to your real definitions.
More information: Scripting JMeter Assertions in Groovy - A Tutorial

Capture time difference between values of two regular expression reference names in Jmeter

I defined regular expressions in my JMeter test plan and I'm able to capture the values in simple variables in user.variables. But I'm trying to calculate the time difference between two variables as follows in Beanshell post processor and I'm not getting any result in my report.
import javax.xml.bind.DatatypeConverter;
vars.put("old_date_submitted", "submittedDate"); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", "succeededDate");
vars.put("old_date_running", "runningDate");
Calendar cal_s = DatatypeConverter.parseDateTime(vars.get("old_date_submitted"));
Calendar cal_c = DatatypeConverter.parseDateTime(vars.get("old_date_succeeded"));
Calendar cal_r = DatatypeConverter.parseDateTime(vars.get("old_date_running"));
Date new_date1 = cal_s.getTime(); // submitted Time
Date new_date2 = cal_c.getTime(); // succeeded Time
Date new_date3 = cal_r.getTime(); // running Time
long new_date1_ms = new_date1.getTime(); // submitted Time
long new_date2_ms = new_date2.getTime();
long new_date3_ms = new_date3.getTime();
log.info("Date in milliseconds: " + new_date1_ms);
long delta1 = new_date2_ms - new_date1_ms; //calculate the difference (succeededDate - submittedDate)
long delta2 = new_date3_ms - new_date1_ms; //calculate the difference (runningDate - submittedDate)
vars.put("delta1", String.valueOf("delta1")); // store the result into a JMeter Variable
vars.put("delta2", String.valueOf("delta2")); // store the result into a JMeter Variable
This bit:
vars.put("old_date_submitted", "submittedDate"); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", "succeededDate");
vars.put("old_date_running", "runningDate");
seems odd to me. Given:
submittedDate, succeeddedDate and runningDates are regular expr. reference names
My expectation is that you should be using JMeter Variables instead of hardcoded strings there, so you should change your code to look like:
vars.put("old_date_submitted", vars.get("submittedDate")); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", vars.get("succeededDate"));
vars.put("old_date_running", vars.get("runningDate"));
So most likely your code is failing at DatatypeConverter.parseDateTime.
Next time you face any problem with your Beanshell scripts consider the following troubleshooting techniques:
Check jmeter.log file - in case of Beanshell script failure the error will be printed there
Add debug(); directive to the very beginning of your Beanshell script - it will trigger debugging output to stdout
Put your Beanshell code in try/catch block like:
try {
//your code here
}
catch (Throwable ex) {
log.error("Something went wrong", ex);
throw ex;
}
This way you get more "human-friendly" stacktrace printed to jmeter.log file.
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using Beanshell in JMeter tests.

Resources