Jmeter while controller doesn't seem to evaluate variables as numbers - xpath

I am writing a jmeter script that keeps loading data until a table reaches a specified size. I have a while loop, in which I have one HTTP Sampler to loads the data, then another HTTP Sampler with an XPath Post-processor to check the table size (they call two different APIs). The reference variable of the XPath Post Processor is currentSize and I have a user defined variable maxSize, but using ${currentSize} < ${maxSize} as the condition for the while loop creates an infinite loop.
Thinking maybe the problem is that the output of XPath is a string, I've tried doing various things in beanshell to coerce it to a number, but I'm a beanshell noob, so I haven't been successful with that either. Can anyone guide me about how to get jmeter to recognize a variable as a number? (Preferably a decimal, but if I have to round to an int, I can live with that.)
Thanks!

I think using __javascript(parseInt()) should suffice for you to check the condition.
e.g.
${__javaScript(parseInt(${time_elapsed_string}) < parseInt(${duration}))}

Assuming that you have following variables:
currentSize
maxSize
continue
where continue is set via User Defined Variables and has the value of true
You can use following Beanshell code to check if current size is equal or greater than maximum size:
import java.math.BigDecimal;
String currentSize = vars.get("currentSize");
String maxSize = vars.get("maxSize");
BigDecimal currentSizeNumber = new BigDecimal(currentSize);
BigDecimal maxSizeNumber = new BigDecimal(maxSize);
if (currentSizeNumber.compareTo(maxSizeNumber) > -1){
vars.put("continue", "false");
}
Make sure that following criteria are met:
Your While Controller has ${continue} as a condition
Beanshell Sampler, Pre / Post Processor or Assertion with the code above is added as a child of the While Controller
See How to use BeanShell guide for more details and kind of Beanshell cookbook.
Everything should work this way.
Hope this helps.

Related

Jmeter - Calling javascript using JSR223 Post processor

I capture 6 elements using a regular expression. say
Variable : UserDetails
Regular Expression : loadHeadWorkFlow\('(.+?)','(.+?)','(.+?)','(.+?)','(.+?)','(.+?)','/I
Template : $1$$2$$3$$4$$5$$6$
Now I could access these values via UserDetails_g1, UserDetails_g2.....UserDetails_g6
Next, these 6 values need to be encrypted using a javascript file. The file contains the logic.
How should my code be using JSR223 post processor?
The steps that I followed:
1.
load('Encryption.js');
var result = encrypt("${UserDetails_g1}","password");
log.info("encrypted value is "+result);
vars.put("LoginDataString",result);
var result1 = encrypt("${UserDetails_g2}","password1");
vars.put("UserId",result1);
var result2 = encrypt("${UserDetails_g3}","password2");
vars.put("RoleId",result2);
First value is encrypted correctly. But the other values aren't correct. If I add individual post processors for every variable. All the encrypted values show correctly.
Is there a way where I could use a single post processor to perform all the 6 encryptions. Thanks in advance
Regards,
Ajith
Use vars instead of ${} syntax
var result = encrypt(vars.get("UserDetails_g1"),"password");
log.info("encrypted value is "+result);
vars.put("LoginDataString",result);
var result1 = encrypt(vars.get("UserDetails_g2"),"password1");
vars.put("UserId",result1);
var result2 = encrypt(vars.get("UserDetails_g3"),"password2");
vars.put("RoleId",result2);
From JMeter perspective there is no problems, just check that your UserDetails_g2 variable has anticipated value using Debug Sampler and View Results Tree listener combination., the you might want to check this encrypt() function implementation.
Another possible reason is this JavaScript language selection itself, the Nashorn engine performance is a big question mark when it comes to the load, according to JMeter Best Practices it's recommended to use Groovy language for scripting so you might want to consider re-writing the function in Groovy

Jmeter - Break down huge JDBC query into multiple JDBC queries

I want to perform jdbc query which returns 700K+ rows, then build my logic based on that, but when try to execute response time is too long, so i need to break down on multiple queries, each returning ex:1000 results.
My architecture is like:
001_1 JDBC max_value - Defines the maximum value, of that 700K, which is increasing all the time.
001_1 JDBC MAIN - This JDBC i want to break down into multiple JDBC requests.
InIt counter = vars.put("counter","1");
offset_value - counter element
While controller - ${__javaScript(parseInt(vars.get("counter"))<=700)}
If i put hard-code value into the While controller, everything works fine, and my script is working; But when data-base increase the records size, then i need manually to amend the number of the while controller 700, so can cover the next records.
Based on my understanding here i have 3 variables:
max_value = 714K
counter = 1
offset_value = 0
If i try: ${__javaScript(parseInt(vars.get("offset_value")<=parseInt(vars.get("max_value")))== true)}
as a while controller statement, offset_value is still not evaluated, and while controller is not working properly.
How can i compare offset_value vs. max_value, so i can drive my While controller?
Any help is appreciated!
If your parseInt(vars.get("offset_value")) expression is being executed against not-initialised variable it will return NaN so comparing it with a number doesn't make a lot of sense, you need to amend it to something like parseInt(vars.get("offset_value")) || 0 so it would return zero on first iteration.
Also be aware that starting from JMeter 3.1 you should be using JSR223 Test Elements for scripting and correspondingly __groovy() function in the While Controller. More information: Apache Groovy - Why and How You Should Use It
Thanks for the help #Dmitri T; However solution for me was:
1. Initialize the compare value as: JRS233 sample -> vars.put("offset_value","0");
2. ${__javaScript(parseInt(vars.get("offset_value"))<=parseInt(vars.get("max_value_1")),)} -> inside while controller.
3. Counter: Track counter & Reset counter: must me checked both

Jmeter $__Random() with user defined variables

I have an issue I have been struggeling with for some time.
In my script I'm calculating a max and min value. I save it using:
int minWaitPregancy_acutall=0.2*maxWaitPregancyWait;
int maxWaitPregancy_acutall=0.8*maxWaitPregancyWait;
vars.putObject("minWaitPregancy_acutall", minWaitPregancy_acutall);
vars.putObject("maxWaitPregancy_acutall", maxWaitPregancy_acutall);
So far so good, it is saved and I can see it using the debugger.
Now I would like to use it in say a "Uniform Random timer".
I set the constant delay to 0 and in the Random Delay Maximum I try thing like:
${__Random(${__eval(vars.getObject("minWaitPregancy_acutall"))},${__eval(vars.get("maxWaitPregancy_acutall"))})}
For some reason that (and other variations, like skipping __eval) doesn't work I get variations of:
"java.lang.NumberFormatException: For input string: "vars.getObject("minWaitPregancy_acutall")""
So I guess I don't understand how to retrieve and use the data from the user defined variables. Any help??
As per Elements of Test Plan -> Execution Order
0. Configuration elements
1. Pre-Processors
2. Timers
3. Sampler
4. Post-Processors (unless SampleResult is null)
5. Assertions (unless SampleResult is null)
6. Listeners (unless SampleResult is null)
As per User Defined Variables documentation:
The User Defined Variables element lets you define an initial set of variables, just as in the Test Plan.
Note that all the UDV elements in a test plan - no matter where they are - are processed at the start.
It looks like you're using the wrong test element, if you want to calculate a random variable and save it you need to use a PreProcessor, for example User Parameters

How to create simple counter using Beanshell?

I'm trying to create a simple counter that will print the iteration number to the log.
the problem is that I didn't find a way to initialize the int value of i to 0.
if I'll do it inside the Beanshell script it will keep initializing, I need it to run only once at the beginning of the test.
My code:
int i=0;
log.info(string.valueOf(i));
i=i+1;
Add Once Only Controller, under it JSR223 Sampler with the initialization
vars.putObject("i", 0);
Then you can increment it after it (not under the Controller) with other JSR223 Sampler:
myI = vars.getObject("i")
log.info(String.valueOf(myI));
vars.putObject("i", ((Integer)myI+1));
It is recommended to avoid scripting where possible, and if you cannot live without scripting you should be using the most performing option which is JSR223 Test Elements and Groovy language.
Particularly your case can be implemented without any scripting, you can use the following JMeter Functions:
__log() - which prints an arbitrary message to jmeter.log file
__iterationNum() - which returns the number of current iteration
So if you use the statement like: ${__log(Current iteration is: ${__iterationNum},,,)} JMeter will return it where the function is called and additionally print the corresponding message to the log file.
Demo:
You can install __iterationNum() function as a part of Custom JMeter Functions bundle using JMeter Plugins Manager

How to make jmeter while controller work

I'm having trouble getting the while controller to work in jmeter.
I've a feeling that I read that it doesn't re-evalute user defined variables, so I am trying to use properties instead.
I start off by using a BSF assertion to set a property called keepLooping
${__setProperty(keepLooping, true)};
This seems to work as it enters the While controller with a condition of
${__property(keepLooping)}
But I cannot for the life of me get it to change that property to something else. I want it to change the property depending on the resulting text of an http request.
So I am using a Regular Expression Extractor to set a variable, which I can see is getting set. Then I am trying to use a BSF assertion to set the keepLooping property on the basis of the variable that I have set. I am using javascript as follows:
log.info("IM IN HERE");
log.info("props is "+props);
//log.info("props keep looping is "+props["keepLooping"]);
if (${surveyRequired} == false){
log.info("IM IN HERE 1A and props is "+props);
${__setProperty(keepLooping, true)};
log.info("IM IN HERE 1B");
}
else {
log.info("IM IN HERE 2A");
${__setProperty(keepLooping, false)};
log.info("IM IN HERE 2B");
}
I can't figure out how to set the property with javascript - I've tried several things. Can anyone help? Many thanks!
Also can anyone recommend a good resource that negotiates what seem to be the many 'quirks' of jmeter? Many thanks!
"I've a feeling that I read that it doesn't re-evalute user defined variables" -- I use JMeter 2.9 and it really does. I use user defined variable in order to count number of loops. It looks like: ${__javaScript(${MY_USER_DEFINED_VARIABLE}>0)}. The only one annoying thing is that I have to get value of variable, increment it, cast to string (toString() in Groovy), and then put new value into MY_USER_DEFINED_VARIABLE (by using vars.putObject("MY_USER_DEFINED_VARIABLE",localBSFVariable))
Using vars.put or props.put will help, as explained in detailed in detail in this jmeter thread.

Resources