How to parametrize number of threads in JMeter 5.2.1 - jmeter

I have a JMeter 5.2.1 project where in the SetUp thread I generate properties with names like ThreadGroupName1-NumberOfThreads, ThreadGroupName2-NumberOfThreads, etc. with values representing integers.
Now, I wish to access these properties in thread groups named ThreadGroupName1, ThreadGroupName2, etc. to parametrize the number of threads. I tried something like ${__jexl3(props.get(threadName + "-NumberOfThreads"))} but it fails as threadName evaluates to standardjmeterengine.
Also, I tried to use ctx but ctx.getThread() and ctx.getThreadGroup() but they evaluate to null.
So far what 'works' for me is ${__jexl3(props.get("ThreadGroupName1-NumberOfThreads"))} but I want it be parametrized by the name of the thread group.
Is it possible to do this?
Is this threadName returning standardjmeterengine a bug?
Update: In fact, the easiest 'solution' that provides the parametrized number of threads there is ${__P(ThreadGroupName1-NumberOfThreads)} and what I want is to generate this key ThreadGroupName1-NumberOfThreads to be something like ${MyCurrentGroupName}-NumberOfThreads, effectively providing a way to have an abstract method like
int GetNumberOfThreads(string threadGroupName)
{
return properties.get(threadGroupName + "-NumberOfThreads";
}
Similarly, I wish to use this patter in Constant Throughput Timer as well with another prefix like -Rpm.

I don't think you can use any JMeter Function in the "Number of Threads" field of the Thread Group so this is not something you can do via UI. If you believe this is something everyone needs you can consider raising an enhancement request
As a workaround you can
Set the number of threads to 1
Add If Controller to the Thread Group and use the following __groovy() function as the condition:
${__groovy(ctx.getThreadNum() == 0 && vars.getIteration() == 1,)}
Add JSR223 Sampler as a child of the If Controller and put the following code into "Script" area:
SampleResult.setIgnore()
2.upto(props.get(ctx.getThreadGroup().getName() + '-NumberOfThreads') as int, { ctx.getThreadGroup().addNewThread(0, ctx.getEngine()) })
This way each thread Group will normally start with 1 thread, however this thread will read the property you defined earlier and add as many threads as needed.

You can use JMeterContext's getThreadNum to get thread number (increment, because it starts with 0)
${__jexl3(props.get("ThreadGroupName"))}${__jexl3((ctx.getThreadNum()+1) + "-NumberOfThreads" )}

Related

How to pass ${__threadNum} value in selenium javascript?

I used Webdriver sampler and write selenium -Javascript. Now in my script for achieving some result we need total number of users so I want to know how add ${__threadNum} value in my script?
or is there any way when multiple users run and some operations execute for only one user?
Either put the ${__threadNum} function to the "Parameters" section and refer it in the script as WDS.args[0] where required
var threadNum = WDS.args[0]
Or use WDS.ctx shorthand for JMeterContext class, there you will have access to getThreadNum() function. It will return zero-based number of thread so to get the same value you will need to increment it by 1
var threadNum = (WDS.ctx.getThreadNum() + 1)
Demo:
More information: The WebDriver Sampler: Your Top 10 Questions Answered article for more information if needed

JMeter If Controller

not too sure if this is a user error but I can't seem to get this working. I have a test that returns 200 and this always hits the If controller, but the following fails.
I get a productID, if this is nested then i get the first one.
Regex is
prodID
"ProductId":(.*?),
$1$
0
Then as I want to use this in another thread group I cjhange to a property:
${__setProperty(prodID-${__threadNum},${prodID},)}
Then i use If Controller as
${__P(prodID-${__threadNum})} == "18"
Then it runs the same regex, but this time with $2$
Problem is that the If Controller isn't getting run on any, is there a way I can see this, or even is the above correct?
Thanks
The If Controller run its children if the expression evaluates to true
You're giving 18 == "18", it is not equal to true therefore the children are not getting executed.
I would suggest using __groovy() function instead like:
${__groovy(props.get('prodID-' + ctx.getThreadNum()).equals('18'),)}
where
props is a shorthand for Properties class instance holding JMeter Properties
ctx is a shorthand for JMeterContext class instance
See Top 8 JMeter Java Classes You Should Be Using with Groovy article for more information on this and other JMeter API shorthands

How to pass a 2-D array from one thread to another thread in Jmeter

So I am using a bean shell post processor and towards the end I am storing the result in a 2-D array. Result is stored this way.
testArray[0][0] = "1"
testArray[0][1] = "Test"
testArray[1][0] = "2"
testArray[1][1] = "STG"
My requirement is that I need to pass this 2-D array to the next thread. How am I supposed to proceed ?
First of all since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting so consider migrating to Groovy.
Coming back to your question just use props shorthand like:
In first thread:
props.put("testArray", testArray);
in the other thread:
testArray = props.get("testArray");
you might also want to add the current thread number as the prefix/postfix so different threads could have different arrays with separate values like:
props.put("testArray_" + ctx.getThreadNum(), testArray);
where ctx stand for JMeterContext class instance
More information on these ctx, props and other JMeter API shortcuts available for JSR223 Test elements: Top 8 JMeter Java Classes You Should Be Using with 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

Resources