JMeter - Variable set in preprocessor is not available to sampler - java

I have a relatively simple JMeter test plan setup as shown here:
https://imgur.com/c8BIzBB
The relevant part of this is the BeanShell Preprocessor (shown as Setup element data) and its relationship to the HTTP Request sampler (shown as POST /elements). Both of these are inside a Loop Controller (shown as Do a few times).
The Preprocessor gets an array of data stored on the bsh.shared object and randomly selects one item. It then sets a variable called elementTypeId.
When I run this test, elementTypeId gets logged (and I therefore assume is set) correctly. However, the first time around, the variable is not set correctly and still appears as ${elementTypeId}. Further samples appear to be set but use the n-1th value.
The first, failing sample is shown here: https://imgur.com/Gj2YAje
The final sample (and logged values) are shown here: https://imgur.com/OW5HSsS
Setup element data - BeanShell Preprocessor code:
import java.util.Random;
import com.eclipsesource.json.*;
Random rand = new Random();
int idx = rand.nextInt(bsh.shared.elementTypes.size());
JsonValue elementType = bsh.shared.elementTypes.get(idx);
String elementTypeId = String.valueOf(elementType.get("id").asInt());
log.info(elementTypeId);
vars.put("elementTypeId", elementTypeId);
It looks to me as if the sampler is firing before the preprocessor has set the variable - which seems counter to what should be happening.
Update following UBIK's answer
When I disable the SetQueryParams PreProcessor, it appears that the variable is set correctly (although the request fails as it needs a query parameter to be added).
SetQueryParams PreProcessor:
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
if (sampler instanceof HTTPSamplerBase &&
sampler.getMethod().equalsIgnoreCase("post")) {
// add query parameter to url
var customPath = sampler.getPath() + '?' + sampler.getQueryString();
sampler.setPath(customPath);
// remove query parameter from body
arguments = sampler.getArguments();
while (arguments.getArgumentCount() > 1) {
arguments.removeArgument(arguments.getArgumentCount() - 1);
}
sampler.setArguments(arguments);
}
Is it possible to have both preprocessors applied to the POST request?

I think you issue might be coming from the other PreProcessor :
SetQueryParams PreProcessor
As per scoping rules , this one runs for every HTTP Sampler.

Check in console for the exception thrown.
try resolving that
if nothing is working please copy your script, delete Beanshell preprocessor and add BeanShell again and paste your script.
This may be silly but it worked for me.

Related

is it possible to delete only one of the returns from the Jmeter result tree? Type specify?

I know it is possible to delete the entire Jmeter result tree, through the code:
import org.apache.jmeter.gui.GuiPackage;
import org.apache.jmeter.gui.JMeterGUIComponent;
import org.apache.jmeter.gui.tree.JMeterTreeNode;
import org.apache.jmeter.samplers.Clearable;
log.info("Clearing All ...");
guiPackage = GuiPackage.getInstance();
guiPackage.getMainFrame().clearData();
for (JMeterTreeNode node : guiPackage.getTreeModel().getNodesOfType(Clearable.class)) {
JMeterGUIComponent guiComp = guiPackage.getGui(node.getTestElement());
if (guiComp instanceof Clearable){
Clearable item = (Clearable) guiComp;
try {
item.clearData();
} catch (Exception ex) {
log.error("Can't clear: "+node+" "+guiComp, ex);
}
}
}
but I didn't want to delete the entire result tree, only the returns that returned with status == 500. Because my api returns 500 until the callback is available for consultation, when it finds the callback it returns "success", so while the api keeps retrying, these retries show up as an error in the report,but in fact the callback has not returned yet, when it returns the api returns the callback and is successful. I would like to remove these requests from the report, which are retry.
Add a JSR223 Post Processor with following code to ignore the test results when the response code is 500
if (prev.getResponseCode()=="500"){
prev.setIgnore()
}
prev - (SampleResult) - gives access to the previous SampleResult (if any)
API documentation for prev variable (SampleResult)
I don't think it's possible without modifying JMeter source code or heavily using reflection. In any case the answer will not fit here.
In general:
You should be using JMeter GUI only for tests development and debugging, when it comes to test execution you should run your test in command-line non-GUI mode
You should not be using listeners during test execution as they don't add any value, just consume valuable resources, all the necessary information is stored in .jtl results file
There is Filter Results plugin which allows removing the "unwanted" data from the .jtl results file
You can also (as well) generate the HTML Reporting Dashboard out of the .jtl results file, the Dashboard has its own responses filtering facilities
guys. First, thanks for the answers, I ended up giving up on the idea of ​​removing the result from the tree and looking for a way to modify the way that result is presented.
I made a beanShell assertion, so that if Status==500, it would return "Success" in the result tree:
BeanShell
I also made it so that if it were a new attempt the name displayed in the results tree would indicate this, leaving the api name mutable depending on the return:
api name = variable
and I have this logic:
import org.apache.jmeter.samplers.SampleResult;
//process main sample
if (${status} == 500) {
SampleResult.setResponseCodeOK();
SampleResult.setSuccessful(true);
vars.put("Api_Fake_Client_name", "API_FAKE_CLIENT_RETRY");
I will configure the answers in the other conditions, but I believe that this way I will be able to solve my problem because the new attempts no longer appear as an error.

How to pass Table Field as import parameter to SAP RFC using JAVA(JCO3)

Following i my code in JCO3.0 to connect to RFC and get the data from function module:
try {
JCoDestination destination = JCoDestinationManager.getDestination(DESTINATION_NAME);
JCoFunction function = destination.getRepository().getFunction("funtion_abap");
***function.getImportParameterList().setValue("IM_ID_NAME", "MTC_ZPR008_TEMPB");***
function.execute(destination);
JCoTable table = function.getTableParameterList().getTable("export_table");
}
catch(Exception e){
}
Following is my ABAP function:
CALL FUNCTION 'funtion_abap' DESTINATION m_vsyid
EXPORTING
IM_ID_NAME = table_vname
IMPORTING
export_table = table_tvarvc
EXCEPTIONS
system_failure = 1
communication_failure = 2
resource_failure = 3
OTHERS = 4.
following is an error m getting while passing String as import parameter while it wants Table field as import parameter:
Exception in thread "main" com.sap.conn.jco.ConversionException: (122) JCO_ERROR_CONVERSION: Cannot convert a value of 'MTC_ZPR008_TEMPB' from type java.lang.String to TABLE at field IM_ID_NAME
at com.sap.conn.jco.rt.AbstractRecord.createConversionException(AbstractRecord.java:468)
at com.sap.conn.jco.rt.AbstractRecord.createConversionException(AbstractRecord.java:462)
at com.sap.conn.jco.rt.AbstractRecord.setValue(AbstractRecord.java:2958)
at com.sap.conn.jco.rt.AbstractRecord.setValue(AbstractRecord.java:4074)
at com.amgen.rfc.RFC_Connection.main(RFC_Connection.java:47)
Please tell me how to solve this problem.
The RFC definition and your code are in direct opposition. According to the ABAP function (as far as I read it) the result of the call is the value in field IM_ID_NAME and the table is the input parameter.
I'm not 100% familiar with the declaration of RFCs in ABAP (I only know the Java side of it), but if I interpret the error message correctly, the table seems to be in the input parameter list rather than the table parameter list (not usual but not never seen before, either). So instead of getTableParameterList you will possible have to call getInputParameterList. Also you should omit the setting of the field IM_ID_NAME because that's the response value and resides in the output parameter list.
I know the question is quite old but someone may find my response useful one day since I had the same problem:
JcoTable tab = function.getImportParameterList().getTable("IM_ID_NAME");
tab.appendRow();
tab.firstRow(); // I'm not sure if this is actually reqiured
tab.setValue("PARAM_NAME", paramValue);

Create a Java Request in jMeter for validating multiple variables

Here in My HTTP Request I extracted some variables using JSON Path Extractor. I want to create a Java Request it will validate the above variables. i.e I want to check the value of reqVar1 is equal to resVar1 or not and reqVar2 is equal to resVar2 or not like that.
You are making things over complicated, you could achieve the same using normal Response Assertion.
For example, if you have a JMeter Variable ${var1} and you need to compare it to ${var2}, ${var3} and ${var4} you can just configure the Response Assertion like:
More information on conditionally marking sampler results as successful or failed: How to Use JMeter Assertions in Three Easy Steps
Instead of Java Request sampler, you can add BeanShell Assertion to compare the values. following is the code:
if(vars.get("reqVar1").equals(vars.get("resVar1")))
{
if(vars.get("reqVar2").equals(vars.get("resVar2")))
{
SampleResult.setResponseCode("200");
SampleResult.setResponseMessage("SUCESS");
}
else{
SampleResult.setResponseCode("403"); // keep error code as per your wish
SampleResult.setResponseMessage("reqVar2 and reqVar2 are NOT same" + vars.get("reqVar2") + vars.get("resVar2"));
}
}
else{
SampleResult.setResponseCode("403"); // keep error code as per your wish
SampleResult.setResponseMessage("reqVar1 and reqVar1 are NOT same" + vars.get("reqVar1") + vars.get("resVar1"));
}
Add the BeanShell Assertion as a child element to the HTTP Sampler in which you are getting the values for reqVar1, reqVar2, resVar1, resVar2
Once the decision is taken based on If condition, you can change the response code and message using SampleResult
Check the following reference that shows all methods available to you:
https://jmeter.apache.org/api/org/apache/jmeter/samplers/SampleResult.html
Image reference:

In JMeter java api how to set POST Form values in a PreProcessor sampler?

In a PreProcessor I am writing I can successfully update GET query string via sampler.
However if I use the same approach with POST, while I can list the FORM fields via getArguments(), the value does not get set.
Arguments arguments = sampler.getArguments();
for (int i=0; i<arguments.getArgumentCount(); i++) {
Argument argument = arguments.getArgument(i);
if (argument.getName().equals("page_submission_id")) {
String newVal = "8743718386872";
argument.setValue(newVal);
System.out.println("Setting arg["+argument.getName()+"] to["+newVal+"]");
}
}
sampler.setArguments(arguments);
printArgs(arguments);
The output from this shows Arguments values are unchanged.
Setting arg[page_submission_id] to[8743718386872]
Arguments After
...
Found arg[page_submission_id] is[XXXXXXXXXXXXX]
...
Having dug into the jmeter code a bit further, there is a "runningVersion" attribute of an Attribute object which (via isRunningVersion()) is set true.
I have tried a few ways to get round this:
force runningVersion to false - then values are set but a GET message is sent
create a new Arguments object and add new Argument entries to it with values - this does not change the values
Can anyone point out the official way to set POST FORM field values before they get sent?
Thanks
Well, you assigning a new value to an argument, but I fail to see where you updating sampler's arguments with the argument having the new value.
I'm a strong believer of KISS principle so instead of adding some more lines I would recommend simplifying your script as follows:
import org.apache.jmeter.config.Argument;
sampler.getArguments().removeArgument("page_submission_id");
sampler.addArgument("page_submission_id","8743718386872");
Also I hope you're using JSR223 PreProcessor and Groovy language.
I managed to resolve this:
(initially) by cleaning up the Thread Pool, as my initial
attempts had included a number of things like "Regular Expression
Extractors" and "User defined variables". Once those were removed
the approach I was using successfully changed the argument values, and
(when deeper in to my setup the problem came back) by adding the creation of a new Argments object and inserting (in the same order) new Argument objects with the value set as I require. Then setting the sampler to use that new Arguments object.
Arguments newArgs = new Arguments();
Arguments arguments = sampler.getArguments();
for (int i=0; i<arguments.getArgumentCount(); i++) {
Argument argument = arguments.getArgument(i);
HTTPArgument newArg = new HTTPArgument();
newArg.setName(arguments.getName());
if (arguments.getName().equals("field_to_replace")) {
newArg.setValue("new value");
}
else {
newArg.setValue(arguments.getValue());
}
newArgs.addArgument(newArg);
}
sampler.setArguments(newArgs);
My take is that this down to the "if (isRunningVersion())" test within setProperty() used by "Argument.setValue()" which I'm tripping over.
While this appears to work (for my test cases so far) I appreciate that overriding this may not be the correct formal approach.

Variable Path Param for REST service testing in Jmeter

I'm testing RESt service which has path parameter.
/my-service/v1/Customer/order/{ordernumber}
I want to increment the number by 1 for each request. How to achieve this in Jmeter? Till now i had been passing a fixed path param, therefor our test result were on only one input parameter.
/my-service/v1/Customer/order/5247710017785924
The good point to start with is putting your initial order value into User Defined Variable
Given start order as "5247710017785924" you need to create an "ordernumber" variable and set it's value to 5247710017785924.
After each request you can increment variable value by adding BeanShell postprocessor to your HTTP Sampler with following code:
long ordernumber = Long.parseLong(vars.get("ordernumber"));
ordernumber++;
vars.put("ordernumber",String.valueOf(ordernumber));
And set ordernumber in your HTTP Sampler path as
/my-service/v1/Customer/order/${ordernumber}
None of the solutions worked for me. Here is what I did
Define HTTP request as shown below and add path /api/v2/state/find/${id} to the request
Right click on HTTP request --> Preprocessor -> User Parameters ->Add variable -> input id and it's value
Start HTTP request, this should work
Use JMeter Counter component to increment variable.
This question is path parameter related, where the value of the order number is incremented by 1 in each successive request. But I faced a scenario where I got a list of order numbers and I had to make request for those order numbers. So, I am gonna answer this question with respect to that, this solution can be applied in both the scenarios.
What I did is put all the parameter paths in a CSV file, like this -
/my-service/v1/Customer/order/5247710017785924
/my-service/v1/Customer/order/5247710017785976
/my-service/v1/Customer/order/5247710017785984
/my-service/v1/Customer/order/5247710017785991
Then I iterated through the list of paths in the CSHTTPle and made http request to the server. To know how to iterate through the CSV file and make http request in Jmeter, you can check this link:
https://stackoverflow.com/a/47159022/5892553
You can use a JMeter Counter:
right click on your Thread Group (under the Test Plan)
select Add–>Config Element–>Counter
set the Starting value (0), Increment (1), Maximum value, Exported Variable Name ("ordernumber")
Then you can use the exported variable name as path param:
/my-service/v1/Customer/order/${ordernumber}
I used a BeanShell PreProcessor to generate an id
vars.put("id", UUID.randomUUID().toString());
Then used the path Http Request
/api/v1/event/${id}/
BINGO!!!

Categories