Reputation: 417
[REVISED ORIG POST FOR EASIER REFERENCE]
Running JMeter 2.13 r1665067, I'm performing API testing doing basic CRUD functions using HTTP Requests from JMeter to a database where the 'id' field value is sporadically being "merged" with the hard-coded 'baseUnitValue' field value resulting in a failure and a stack trace message of "Obj is not found".
CREATE New Record
HTTP POST
"id": 0,
"schedulePeriodId": 1259810849,
"amount": null,
"baseUnitValue": 10.50,
"procValue": "G0040",
RESPONSE
"id": 1259811045,
"schedulePeriodId": 1259810849,
"amount": null,
"baseUnitValue": 10.50,
"procValue": "G0040"
RegEx Extractor
Apply to: Main Sample only
Field to check: Body
Ref Name: baseUnitId
Reg Exp: \"id":(.+?)\,
Template: $1$
Match No: 1
Default: None
UPDATE (original)
HTTP POST
${__BeanShell(return vars.get("foobar").replaceAll(vars.get("baseUnitFieldValue")\,"11.50");,)}
Where it's using/interpreting foobar to contain:
"id": 12599511.507,
"periodId": 1259810849,
"amount": null,
"baseUnitValue": 11.50,
"procValue": "G0040"
RESPONSE
Object with id 12599511 not found...
After a number of runs and investigations, a pattern emerged:
Basically, every 1000 records would fail when the 'id' would end in xxxxxx1045. I would "appear" the last digits of the 'id' value was being evaluated each time, and when it would end in 1045, it was rounded to 10.50.
Thanks to the assistance from @kiril-s and @dmitri-t, the following solution has been created.
First, I added 2 new User Defined Variables
CREATE (added BeanShell PreProcessor)
HTTP POST
"id": 0,
"schedulePeriodId": 1259810849,
"amount": null,
"baseUnitValue": ${RND},
"procValue": "G0040",
BeanShell PreProcessor
Parameters: ${RND1}, ${RND2}
Script:
import java.util.*;
String [] params = Parameters.split(",");
double rangeMin = Double.valueOf(params[0]);
double rangeMax = Double.valueOf(params[1]);
Random r = new Random();
double randomValue = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
vars.put("RND",randomValue.toString());
//System.out.println(randomValue);
There is also a REGEX to parameterize the "id" field value assigned by the database. This permits proper READ and DELETE functions by appending the associated URL with the parameter.
When performing the READ HTTP Request, added a BeanShell PostProcessor to the existing 2 REGEX. REGEX 1 Ref Name: foobar Reg Exp: (?s)(^.*)
REGEX 2
Ref Name: origFieldValue
Reg Exp: \,"baseUnitValue":(.+?)\,
BeanShell PostProcessor
Reset Interpreter: False
Parameters: ${RND1}, ${RND2}
Script:
import java.util.*;
String [] params = Parameters.split(",");
double rangeMin = Double.valueOf(params[0]);
double rangeMax = Double.valueOf(params[1]);
Random r = new Random();
double randomValue = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
vars.put("newFieldValue",randomValue.toString());
//System.out.println(randomValue);
This permits the passing of a different value (newFieldValue) to the 'baseUnitFieldValue' without hard-coding.
UPDATE (added JSR223 PreProcessor)
HTTP POST
${baseUnitValueBody}
JSR223 PreProcessor
Language: groovy
Parameters: "newFieldValue"
Script:
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
import org.apache.jmeter.protocol.http.util.HTTPArgument;
vars.put("foobar", vars.get("foobar").replace(vars.get("baseUnitFieldValue"),vars.get("newFieldValue")));
Also notice the change from replaceAll
to replace
.
Now, the 'baseUnitValue' is always unique and the 'id' field is not being evaluated and transformed every 1000 records. I've run using 500 thread users @ 1 loop and 1000 users @ 3 loops. The original issue no longer occurs. Thanks again to @dmitri-t and @kiril-s.
Additional feedback welcome.
Upvotes: 1
Views: 148
Reputation: 168157
This may happen due to Beanshell interpreter performance problem. It is recommended to use JSR223 Test Elements and Groovy language for scripting when it comes to high loads.
First of all download groovy-all.jar, drop it to Jmeter's "lib" folder and restart JMeter to pick the jar up.
Redesign your UPDATE record as follows:
In JSR223 PostProcessor:
Put the following code into "Script" area:
vars.put("foobar", vars.get("foobar").replaceAll(vars.get("baseUnitFieldValue"),"11.50"));
It should fix your problem. See Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! for detailed explanations, instructions on installing groovy engine support and scripting best practices.
Upvotes: 0