How to use BeanShell: JMeter's favorite built-in component
Posted by Dmitri Tikhanski
Beanshell is the most advanced of JMeter built-in components which supports Java syntax and extends it with scripting language features like loose types, commands and method closures. If your test case is not very common and implementation via embedded JMeter components is tricky or even impossible, using Beanshell is the best option to get things done.
Beanshell entities available in JMeter have access to both internal JMeter APIs and any external classes which are loaded into JMeter classpath (make sure that you drop necessary jars into /lib/ext folder of your JMeter installation and place all necessary “import” statements at the top of your Beanshell scripts).
JMeter provides the following Beanshell-enabled components:
- Beanshell Sampler – a standalone Sampler
- Beanshell PreProcessor – a Pre Processor to another Sampler which is executed before Sampler and can be used for pre-requisites setup, i.e. to generate some input
- Beanshell PostProcessor – a Post Processor which is executed after Sampler and can be used for recovery or clean up
- Beanshell Assertion – an advanced Assertion with full access to JMeter API .Java conditional logic can be used to set assertion result
- __Beanshell function – a JMeter Function which allows the execution of custom Beanshell code during a Sampler run
Changing JMeter Variables on the fly
Assuming that you have a User Defined Variable called "continue" with the value of "true" which is being used somewhere in the While loop. You can set it to "false" as simple as follows:
Convert JMeter variable to a JMeter Property
Given variable "some_variable" you need to cast to JMeter Property with the same name to use, i.e. in another Thread Group
Passing Cookies between Thread Groups
Assuming that the HTTP Cookie Manager is enabled, the following code can be used for converting JMeter Cookies into JMeter Properties
After all the cookie information is stored as a JMeter Property and you can reconstruct cookies in another Thread Group
Stopping the test in case of failure
Imagine that you have a 48 hour SOAK test scheduled to run over the weekend which explicitly depends on (for example) the CSV Data Set Config element which requires source CSV files to be present somewhere. You tested it with 1 user and 1 loop on your developer machine and it worked fine.
However when you upload it to your production environment and run headless, JMeter fails to locate the CSV file and all 48 hours are wasted.
To avoid this situation you can use the following check in the very first Beanshell Sampler:
All of the above + BlazeMeter
This is to demonstrate simple Beanshell use case with BlazeMeter.
Given following TestPlan structure:
- Thread Group (1 user, 1 second ramp-up, Forever)
- While Controller with empty condition (Forever once more)
- Counter (Start – 1, Increment – 1, Reference name – Counter)
- HTTP Request (Server Name – example.com)
- BeanShell Post Processor
The BeanShell Post Processor will test if HTTP Sampler Response contains “Example Domain”, if it doesn’t – the test will be failed and stopped immediately. If it does – the test will be stopped after the 3rd iteration. In both cases something is appended to the jmeter.log.
JMeter Pre-defined Beanshell variables
The next section contains the most important and most frequently used JMeter API classes exposed to Beanshell components.
If you look to the bottom of Beanshell Sampler component you’ll see following label:
“The following variables are defined for the script:
SampleResult, ResponseCode, ResponseMessage, IsSuccess, Label, FileName, ctx, vars, props, log”
SampleResult maps to the JMeter class org.apache.jmeter.samplers.SampleResult, all fields and methods outlined in the javadoc can be accessed and invoked.
Sample use case:
ResponseCode is a java.lang.String which stands for sampler response code.
Sample use case:
ResponseMessage is a java.lang.String which represents response message; sample use case is the same as for the ResponseCode.
IsSuccess is java.lang.Boolean which reflects whether sampler succeeded. If it’s set to true – sampler will be considered “passed”, otherwise it will be marked as “failed”
Label is java.lang.String which represents sampler Label. Can be get or set as usual String, will be listed in Test Results as sampler label.
FileName is a java.lang.String which contains beanshell script file name (what is entered in “Script file” stanza of the BeanShell Sampler).
ctx is the most powerful variable exposed to Beanshell. It represents org.apache.jmeter.threads.JMeterContext class which is pretty much JMeter itself, it provides read/write access to underlying JMeter Engine, Samplers and their Results as well as to variables/properties.
vars is the most frequently used component which represents JMeter Variables. It’s an instance of org.apache.jmeter.threads.JMeterVariables class and provides read/write access to current variables, capable of enumerating/changing existing, creating new ones and obtaining nested properties.
All JMeter variables are Java Strings, if you need to put something else to a JMeter variable – you’ll need to cast it to string first.
The following code snippet demonstrates saving previous Sampler response data into a JMeter Variable
Basically it’s the same as “vars”, but it exposes JMeter Properties instead. See JavaDoc on java.util.Properties and JMeter Documentation on JMeter Properties for more information.
The main difference between props and vars is that props have “global” scope, and scope of “vars” is limited to current thread group only.
log represents org.apache.log.Logger class and can be used to append a message to jmeter.log file. See JavaDoc on logger for more details.
Sample use case:
Debugging of Beanshell scripts
As Beanshell is executed within Rhino engine there is no other option to see what’s wrong apart from inspecting jmeter.log file for something like:
Error invoking bsh method
and using System.out.println(“something”) or log.info(“something”) to get to the bottom of where the script fails.