I am trying to print the below code in Beanshell PostProcessor
but i am getting
Code : log.info(ctx.getPreviousResult.getTime());
Error Message: Cannot access field: getPreviousResult
JMeterContext.getPreviousResult() is a function, not field, you need to add parentheses after it
You cannot print a Long value to jmeter.log directly, you need to cast it to String first
There is prev shorthand which stands for parent SampleResult so you can actually shorten your code
Assuming all above amend your code to:
log.info(prev.getTime().toString());
Also be aware that starting from JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language mostly because Groovy has much better performance comparing to Beanshell so consider migrating to JSR223 PostProcessor on next available opportunity, you will not have to change the code.
getPreviousResult is a method so syntax is:
ctx.getPreviousResult().getTime()
So you code should be:
log.info("{}", ctx.getPreviousResult().getTime());
Related
I wrote below given code in Jmeter pre-processor
${__fifoPop(sync_tokensa, gotTokena_1)}
${__fifoPop(sync_tokensaq, gotTokena_2)}
error showing as
Response code:500
Response message:javax.script.ScriptException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script394.groovy: 1: unexpected token: # line 1, column 38.
U0pDVVdtaUJRa0xQSEVodzE1MDEyNTM2MzQ=
As per JSR223 Sampler documentation:
When using this feature, ensure your script code does not use JMeter variables directly in script code as caching would only cache first replacement. Instead use script parameters.
Don't inline JMeter Functions and/or Variables into the Groovy scripts, it may cause either compilation failure or incorrect interpretation or only first value will be used or any combination of all above.
Go for code-based equivalent like:
1.upto(2, { number ->
vars.put('gotTokena_' + number, kg.apc.jmeter.modifiers.FifoMap.getInstance().pop('sync_tokensaq'))
})
More information: Apache Groovy - Why and How You Should Use It
Every time I need to achieve something in Jmeter, I ask a question in SO...
To make a story short: my goal is to read Base64 encoded values from csv file line by line and save them into separate variables. According to this page (in order to decode them), there are functions ${__base64Encode} and ${__base64Decode}. I installed Custom Jmeter Functions Plugin and restarted the Jmeter. Another referral to this answer, there is an advisory to use JSR223 PostProcessor / Sampler, verbatim:
it is recommended to use Groovy for any form of scripting to consider
migrating to JSR223 PostProcessor
so I decided to give it a try. Below is my script to read csv files:
def csvFileLocation = new File("C://JohnDoe//MyWork//sensitive_data.csv")
def lines = csvFileLocation.readLines()
lines.eachWithIndex {line, idx ->
vars.put("Id_value_" + idx, line)
}
${__base64Decode(${Id_value_0}, first_variable)}
${__base64Decode(${Id_value_1}, second_variable)}
${__base64Decode(${Id_value_2}, third_variable)}
Then I saw something interesting:
2018-01-01 12:30:60,767 ERROR o.a.j.p.j.s.JSR223Sampler: Problem in
JSR223 script JSR223 Sampler, message: javax.script.ScriptException:
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed: Script10.groovy: 8: unexpected token: ! # line 8,
column 1. !ßïj[žÿ
I simply decided to test it on https://www.base64encode.org/ with a string this is the test of base64 encoding
However, Jmeter _base64Encode function produces completely different result:
vars.put("jmeter_variable", "this is the test of base64 encoding");
${__base64Encode(${jmeter_variable}, my_variable)}
log.info(${my_variable});
OUTPUT:
JHtqbWV0ZXJfdmFyaWFibGV9
My question: what type of encoding algorithm Jmeter uses? Should I be able to save already encoded values into the csv file and retrieve them to the original value with the help of __base64Decode function? Thanks for the help...
You need to replace these lines:
${__base64Decode(${Id_value_0}, first_variable)}
${__base64Decode(${Id_value_1}, second_variable)}
${__base64Decode(${Id_value_2}, third_variable)}
With these ones:
vars.put('first_variable', vars.get('Id_value_0').decodeBase64() as String())
vars.put('second_variable', vars.get('Id_value_2').decodeBase64() as String())
vars.put('third_variable', vars.get('Id_value_2').decodeBase64() as String())
vars is a shorthand for JMeterVariables class instance, it provides read/write access to JMeter Variables in current test element's scope.
As per JSR223 Sampler documentation you should avoid inlining JMeter Functions and/or variables into Groovy scripts as they may resolve into something which can cause your script compilation failure (like in your case) or unexpected behaviour. Moreover it does not align with Groovy's compilation caching feature therefore performance of your Groovy script even if everything will be fine from syntax perspective will be a big question mark.
So the most "natural" way from Groovy perspective will be using String.decodeBase64() function like demonstrated above. See The Groovy Templates Cheat Sheet for JMeter article to learn what else could be done with Groovy and how.
I am trying to extract key "count" from response data and write it's value (int) in CSV file.
I have used BeanShell PostProcessor for the same.
Below is script I have used:
count = vars.get("count");
f = new FileOutputStream("file path", true);
p = new PrintStream(f);
this.interpreter.setOut(p);
print(count);
f.close();
And JSON sample, I am trying to extract:
{"meta":{"message":"","is_error":false,"count":295,"next":"123","status":1000,"previous":""}
Doing this, "null" gets printed in CSV file.
Please let us know what am I missing here?
It supposed to be 295 gets printed in CSV file.
Check whether your extractor is fetching the correct value. Below, I have used the same code and used regular expression extractor to fetch the values from the json. It is working fine.
Hope it helps.
Update for Reg Ex
Regular expression config;-
Below is to test the regular expression. You can always test your regular expression in view result tree using RegEx Tester:-
Since JMeter 3.1 users are strongly advised to switch to JSR223 Test Elements and Groovy language mainly because Groovy has much better performance comparing to Beanshell.
So I would suggest going for JSR223 PostProcessor in order to extract the "count" value and write it into a file in a "single shot", the relevant code would be something like:
new File('file path') << new groovy.json.JsonSlurper().parse(prev.getResponseData()).meta.count
More details:
Groovy: JsonSlurper
Groovy: Parsing and producing JSON
If I have a BeanShell PostProcessor with the following script:
vars.put("avar", ${__unescapeHtml("<escele>esceleValue</escele>")});
vars.put("bvar", "<escele>esceleValue</escele>");
vars.put("cvar", ${__unescapeHtml(vars.get("bvar"))});
I get the following in the Debug PostProcessor:
avar=<escele>esceleValue</escele>
bvar=<escele>esceleValue</escele>
cvar=<escele>esceleValue</escele>
I would expect cvar's value to match avar's value. Is there a way to do this?
Ultimately I am trying to get a statement like the following to work with escaped XML in the response data. In the process I tried PostProcessor extractors that successfully put all the response data in a variable and then tried to unescape the variable as in the above test case. I assume the issue is the same using a variable or using "prev.getResponseDataAsString()".
vars.put("avar", ${__unescapeHtml(prev.getResponseDataAsString())});
I would recommend stop inlining JMeter Functions and/or Variables into scripting-enabled test elements as it may cause unexpected behaviour w.r.t ValueReplacer and in case of JSR223 Sampler and Groovy language will definitely lead to performance degradation as scripts containing variables and functions references cannot be compiled into bytecode.
Given you:
Already using Beanshell
Know that __unescapeHtml() function is using StringEscapeUtils under the hood according to the function documentation
Why just not to call code directly like:
import org.apache.commons.lang3.StringEscapeUtils;
vars.put("avar", ${__unescapeHtml("<escele>esceleValue</escele>")});
vars.put("bvar", "<escele>esceleValue</escele>");
vars.put("cvar", ${__unescapeHtml(vars.get("bvar"))});
vars.put("dvar", StringEscapeUtils.unescapeHtml4(vars.get("bvar")));
log.info(vars.get("dvar"));
I have a javaScript variable says:
${__javaScript(Math.round(new Date().getTime() / 1000 -18000 )*1000)}
My beanshell code is:
start = vars.get ("startTime-5");
newStart = start + 1000;
startTime-5 is the var for the javaScript code.
When I print newStart I expect to get the calculation of start+1000, but instead what I get is adding "1000" as a string.
For example, if start=14456789000 - what I get is 144567890001000 instead of 14456790000
As per Beanshell Intro
BeanShell emulates typed variables and parameters when they are used. This allows you to "seed" your code with strong types where appropriate. You can "shore up" repeatedly used methods as you work on them, migrating them closer to Java. Eventually you may find that you want to compile these methods and maintain them in standard Java. With BeanShell this is easy. BeanShell does not impose a syntactic boundary between your scripts and Java.
So think of Beanshell as of Java.
Something like:
long start = Long.parseLong(vars.get("startTime-5"));
long newStart = start + 1000;
vars.put("newStart", String.valueOf(newStart)); // if you need the JMeter Variable
should do the trick for you.
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more detailed information on Beanshell scripting in JMeter and for a kind of Beanshell cookbook.