How to Use JMeter While Controller
JMeter's While controller is best suited for advanced scripts which simulate realistic user behaviors. It allows to define a behavior which occurs on a certain condition. Designing realistic behaving users involves designing users whose behavior depends on the server responses, and act accordingly.
This post explores in details various JMeter While usages and explains them thoroughly.
Difference with If Controller¶
The difference is pretty simple to understand:
- If controller children are executed zero or one time when the condition is met,
- While controller children are executed zero, one or multiples times depending how many times the condition is met.
When the while controller children execution is over, it returns to the beginning of the while and evaluates the condition again. If the condition is met, the children are all executed again. An Exit condition is mandatory : something inside the while controller must switch the condition to false at some point, otherwise the while controller will run forever.
If you write your condition directly in Condition it won't evaluate your expression hence it will never become "false". The solution is to wrap your statement into a javaScript function as:
${__javaScript(${counter}<=5)}
Configuration¶
The purpose of the While Controller is to repeat a given set of actions until the condition is broken. While is a basic programming concept to run actions where the number of iterations to run is unknown or varying.
For example, you simulate a user who buys all the goods within a random product category. The number of goods to buy varies depending on the category.
In JMeter, the While controller runs all the Samplers which are located underneath, unless some predetermined “Condition” is “true” where “Condition” could be:
- blank: exits when the last sampler in the loop fails,
- LAST: the same as blank, but with an additional check for the last Sampler before the loop result. If the preceding Sampler is not successful, the While Controller and its children won’t be executed at all,
- JMeter Function or Variable: children will be run until a variable or function evaluation result is false,
- JMeter Property: it works the same way as a Function or Variable, but assumes the value of a JMeter property instead.
Please note the following special behaviors regarding the condition:
- It can be any variable or function that eventually evaluates to the string "false". This allows the use of JavaScript, BeanShell, properties or variables as needed,
- It is evaluated twice, once before starting sampling children and once at end of children sampling, so avoid putting non idempotent functions in Condition (like counters).
Functions¶
JMeter has many built-in functions that can be used to evaluate a while condition.
Many of these functions can be reused in While conditions. Most JMeter variables are stored in String format, so make sure to use the javaScript function or similar to compare the variable value to the string value. Make sure both parts of the condition are of the same type or you will get into trouble. For example, in JavaScript, surround both the variable and the expected value with double quotes to interpret them as strings.
Real-Life Use Cases¶
While with Counter¶
A while can be seen as a for loop when used in conjunction with a counter. The sample JMX can be downloaded here.
This example illustrates how to use JSR223 scripts combined with a While Controller to loop for a given number of iterations. The Thread group contains:
- InitCounter JSR223 Sampler: Initializes the counter to the value 1:
vars.put("counter","1");
- While Controller: It checks for the counter value:
${__javaScript(parseInt(vars.get("counter"))<=5)}
- IncrementCounter JSR223 Sampler: it increments the counter:
int counter = Integer.parseInt(vars.get("counter")) +1;
vars.put("counter",Integer.toString(counter));
As a result, the GET request is executed 5 times, as expected. More advanced while controller uses cases can be found on documentation about JSR223 samples.
E-commerce¶
The following case can be useful:
I have used the same in an eCommerce site, where the condition was that 'User is not allowed to Check-Out products until he purchases items of some amount X' i.e. minimum amount for Check-Out. So we have stored this value of items to be purchased in a Variable and then used the same in While Loop, so that until amount not reached to X, keep of adding products using the samplers which are inside the While loop controller. Once the amount become >= X, the While loop exits and proceeded to Check-Out.
See Working with While Loop In JMeter for more information.
Regexp in While Condition¶
In case you need to check a variable value against a regular expression, you can take a look at JMeter while Loop Regexp to learn more. In Javascript, a string can be matched against a regular expression like in the following example condition:
${__javaScript(! "${CFY_g4}".endsWith('label1') || (! "${CFY_g6}".match('Current Fiscal YTD')) )}
Execute until¶
Suppose you have the following logic inside your thread group:
Thread Group
.. While controller
.. HTTP request
.. Response Assertion
Listener
You want to stop executing the while controller when the response assertion fails.
Thread Group
HTTP Request
${__setProperty(txtFound,FALSE,)}
While Controller
Condition = ${__BeanShell(!props.get("txtFound")}
. . .
[execute your test logic here]
. . .
YOUR HTTP Request
Response Assertion
// set your text assertion here
// this will results in ${JMeterThread.last_sample_ok} = TRUE if text found
IF Controller --FOUND
Condition = ${JMeterThread.last_sample_ok}
HTTP Request
//set-found-condition
${__setProperty(txtFound,TRUE,)} // this will be inverted to FALSE in the next WHILE cycle's condition, WHILE cycle will be exited
The example above makes use of a local variable to stop the while from executing when a given condition is met. This kind of logic can be used in almost all the cases.
Common Error¶
If you get org.mozilla.javascript.EvaluatorException when executing the while controller, double-check the condition syntax and look for any missing double quotes, parenthesis and curly braces.
Common Mistakes¶
This While loop is being executed Infinitely for different conditions like:
${__javaScript("1"!="1")}
This evaluates always to false because both strings are equal.
${__javaScript("1"=="1")}
This evaluates to true all the time.
${__BeanShell(!"1".equals("1"))
Syntax error, missing final } - see JMeter log file.
${__BeanShell("1".equals("1"))
Syntax error, missing final } - see log file
Once fixed, behaves correctly - i.e. does not stop.
${__javaScript("${VariableName}"!="value")}
Won't stop until VariableName is equal to value.
${__javaScript("${VariableName}"=="value")}
As expected, does not run unless VariableName is equal to value.
To avoid any miscomprehension about how to javascript conditions are working, see JavaScript Operators. We recommend you to use javascript conditional evaluation and avoid beanshell. BeanShell support should be removed from JMeter in the Future, in favor of Groovy.
And you, how have you used JMeter While Controller? Share you most useful scripts!