1

The problem

My JMeter test calculates amount of threads that should be allocated to a thread group using JS expressions like this:

  • threadsGroupA expression: ${__javaScript(${__property(threads)}*${__property(threadPercentageA)})}
  • threadsGroupB expression: ${__javaScript(${__property(threads)}*${__property(threadPercentageB)})}

The properties passed to script:

threads=100
threadPercentageA=0.3
threadPercentageB=0.7

The expected result is: 30 threads assigned to group A and 70 threads assigned to group B.

This works as expected on my workstation. However, when I try to run it on a server, it does not create threads unless I use comma as a decimal separator in properties file:

threads=100
threadPercentageA=0,3
threadPercentageB=0,7

I am looking for a way to run the test with same property file in any environment.

What I tried

I have tried to force JVM to use locale with a decimal point . by adding -Duser.language=en -Duser.country=US -Duser.region=us (in different permutations) as variablesJMETER_OPTS, JMETER_LANGUAGE and also directly passed to JMeter as command line arguments(JMeter doc reference). None of that seemed to have any effect.

My thoughts

My conclusion at this point is that the problem is happening in JS engine that evaluates __javaScript()function. If there was a way to set locale for JS engine, I would be able to check this, hence the question in subject.

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
Pavel
  • 318
  • 3
  • 13

3 Answers3

1

Use __groovy function and cast to integer/double the values before multiply:

 ${__groovy(props.get("threads").toInteger() * Double.parseDouble(props.get("threadPercentageB")),)}
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • With little adjustments, groovy approach worked! However I ended up using JavaScript solution based on by Dmitri T's answer, as it was the closest to what I was looking for. – Pavel Jun 10 '21 at 11:47
1

Try using parseFloat() function for your decimal values like:

${__javaScript(${__property(threads)}*parseFloat(${__property(threadPercentageA))})}

If the output is decimal as well - in JavaScript there is Number.prototype.toLocaleString() function where you can explicitly set the locale for the Number object so you will have the confidence that it will return dot or comma no matter where it is run.

Also be aware that JavaScript engine is removed from the latest JDK/JRE versions so if you have a lot of JavaScript in your JMeter tests it makes sense to consider migrating to GraalVM or switching to __jexl3() or __groovy() functions

Dmitri T
  • 159,985
  • 5
  • 83
  • 133
  • There is a syntax error in the order of closing brackets. I think you meant ```${__javaScript(${__property(threads)}*parseFloat(${__property(threadPercentageA)}))}``` (unable to edit myself - too small edit). Found a working solution thanks to you: ended up using `toFixed()` to get integer. Appreciate the useful links! – Pavel Jun 10 '21 at 11:42
1

JS solution

Use parseFloat(), which always expects ., regardless of locale:

${__javaScript((${__property(threads)}*parseFloat("${__property(threadPercentageA)}")).toFixed())} 

Credits for original idea to Dmitri T's answer

Groovy solution

${__groovy((props.get("threads").toInteger() * Double.parseDouble("${props.get('threadPercentageA')}")).round())}

Credits for original idea to user7294900's answer

Note about JMeter thread count handling

Turns out JMeter will not accept number of threads with decimal part, even if it is .0. Therefore, answers above include rounding functions.

Pavel
  • 318
  • 3
  • 13