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.
Related
The following is the code, I have added in my Beanshell Post Processor:
import org.apache.jmeter.services.FileServer;
String path=FileServer.getFileServer().getBaseDir();
String var1= vars.get("Others");
String var2= vars.get("Recommendations");
f = new FileOutputStream("C://apache-jmeter-5.4.1/apache-jmeter-
5.4.1/bin/Output_IndustryType.csv",true);
p = new PrintStream(f);
this.interpreter.setOut(p);
p.println(var1+ "," +var2);
f.close();
But the problem is that the value obtained from these two variables, is a long text, so in the CSV file it is coming in each column as a single text.
And value of Var1, is not coming in the CSV file, and when checked using Degub Sampler it is extracted properly.
Since JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language for scripting so it worth considering migrating and it might be the case it will resolve your issue
If you plan to run your test with > 1 thread (virtual user) the approach is not valid at all as you will be getting random failures and unexpected behaviour due to race conditions when 2+ threads will be concurrently writing into the same file so it makes more sense to consider declaring these Others and Recommendations guys as Sample Variables and store them into the CSV file using Flexible File Writer plugin
I have two variables (create_date) took from SQL queries, and I want to validate the results.
Using Regular Expression I fetch both created date and I want to make sure that the dates is not equal.
I have created the following BeanShell assersion to compare both variables:
enter image description here
however, I'm getting the following error:
enter image description here
You're mixing 2 approaches:
Referencing variables like ${CreateDateBefore} in scripts (which you should not be using at all)
And using vars shorthand for JMeterVariables class instance
Apart from this you're using double to store some form of a timestamp
So you need to update your code like:
String var1 = vars.get("CreateDateBefore");
String var2 = vars.get("CreateDateAfter");
Also be aware that since JMeter 3.1 you should be using JSR223 Test Elements and Groovy language for scripting so consider migrating to JSR223 Assertion
And last but not the least, you can compare 2 JMeter Variables using "normal" Response Assertion configured like:
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
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());
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"));