Beanshell code to call an API, parse JSON response - jmeter

I am trying to implement a logic where i do not want to send HTTP Requests unless an API returns 0 for a field. If i send the requests without monitoring response from this API, my test is invalid. API returns response in JSON, i can parse and extract the data i need to compare. Below is my test structure.
Thread Group
* While Controller
* CSV Data Set Config
* HTTP Request
* JSON Path Extractor
* Constant Throughput Timer
* While Controller Condition: ${__BeanShell(source("function.bsh”))} != “0”
I want to call this API after every 5 minutes and proceed with sending HTTP Requests when field value is 0. I don't want to check before every HTTP Request just once before sending the first request.
Can someone please help me with the beanshell code (function.bsh) to get API response and parse json response ? Was implemented using python as below
max_behind = 0
response = requests.get("https://api")
consumers = response.json().get("consumers")
for total_behind in consumers.iteritems():
max_behind += total_behind[1].get("total_behind")

As Jmeter developers suggested "Better to avoid scripting languages in Jmeter". So in your case use "If Controller" to resolve your blocker. Below are the details
Use regular expression to extract the "API return field" value, once you hold this value in a variable "valueIs". As shown in belo image
Use "If controller " and in condition enter the following value "${valueIs}==1", then add child requests ( next API call/calls) to "If controller". As shown below image

Related

ForEach Controller won't run multiple HTTP Requests

I have a ForEach Controller that loops over an array of values which works. Inside the ForEach block I have two HTTP requests and one extractor.
ForEach Loop {
+ HTTP Request 1 (This uses attribute from ForEach)
+ Extractor
+ HTTP Request 2 (This uses attribute from Extractor)
}
The first HTTP request runs and the extractor as well but the second HTTP request fails to run.
I've checked the logs and nothing is mentioned about this HTTP Request. I also tried moving the Extractor out from under the HTTP Requestor 1 but that also doesn't work.
There is no problem to have multiple Samplers as ForEach Controller children
The possible reasons for not executing the 2nd HTTP Request are in:
Your extractor fails somewhere somehow, double check that the variable is set and has expected value using Debug Sampler and View Results Tree listener combination
Your 2nd HTTP Request configuration is not correct, i.e. invalid characters in "Server Name" field or unsupported protocol or the request is actually being executed but takes too long, etc. I would recommend looking into jmeter.log file as normally it has enough troubleshooting information

How to loop an HTTP request and update the variables each time in Jmeter BeanShell

I have 2 HTTP request: One to GET data from an api and the other to POST data to the api.
The GET request brings several users in JSON. The POST request requires to 1 request per user. Hence I need to:
Loop the same POST request several times depending on the number of users (already did this by using a while controller that checks the number of users from the JSON response).
For each POST request, I need the variables used in such request to be updated depending on the user's information inside the JSON response.
The approach I am attempting is to use BeanShell PreProcessor inside the POST request but I'm having troubles with it.
Suppose one variable is called ${name} in the request body of the POST. I am using a JSON Extractor PostProcessor (On the GET request) path: "Travelers[0].FirstName" that returns the first name of the first user but then I need the second user's name (Travelers1.FirstName) to be assigned to the same variable ${name} before the POST request is sent and so on with every single user.
I want to make a for loop like this:
for (int i = 0; i <= numberOfTravelers; i++) {
vars.put("Name", Travelers[i].FirstName)
}
The problem is that I do not know how to call a JSON path from a JSON response of another previous request. Is there a way to reference the jsonpath to the specific JSON response or a way to save the whole JSON response in a variable and then find the specific value inside that variable as a JSON path.
I have tried this with the JSON extractor but the problem is that if I use the path: Travelers[*].FirstName, it will actually get all the names on the JSON but the variable ${name} will only store ONE name, not all of them as an array that I can later access in my for loop with a normal variable ${name[i]}. That is why I need to access the JSON path from the BeanSheall.
Here a sample of the JSON response:
{
"Travelers":
[
{
"FirstName":"VICTOR",
"Surname":"ORREGO",
"Key":"1.1",
"PassengerRPH":1,
"TypeCode":"ADT"
},
{
"FirstName":"JULIO",
"Surname":"OZAETA",
"Key":"2.2",
"PassengerRPH":2,
"TypeCode":"ADT"
}
]
}
This is the PostProcesor JSON Extractor at the GET request that I'm using. it is currently assigning the first name it gets from the JSON response (Victor) to the variable ${Name}
I need that in the next iteration (of the POST Request) the variable ${Name} to return the next name in that path, which is Julio.
here is the solution..
Add a JSON Extractor to the get request .. use match no -1 to store all Firstnames as show below.
i'm extracting all Firstnames and storing it in JMeter variables with a single JSON extractor
2. To the same get request add a JSR223 Post processor and set the counter value to 1
vars.put("counter","1");
Add a while loop to the test plan and add the following condition to the while loop.
${__javaScript(parseInt(${counter})<=parseInt(vars.get("FirstName_matchNr")),)}
4.To the post request add a JSR223 Pre Processor and add the following code
vars.put("name",vars.get("FirstName_"+vars.get("counter")));
This will store FirstName_Matchno's value in name variable.
Add a JSR223 Post Processor to the POST Request and increment the counter.
int counter = Integer.parseInt(vars.get("counter")) +1;
vars.put("counter",Integer.toString(counter));
You can see in the results its substituting a different name on each iteration of loop
Let me know if it helps..

Manipulating the request body of HTTP thread based on the data extracted from the previous HTTP response

I want to manipulate the request body of HTTP thread based on the data extracted (using 'Regular Expression Extractor') from the previous HTTP response.
Here is the scenario:-
I have extracted the statusFlag and statusId from 'HTTP request 1' as:
Ref name: status
Reg. Exp: "statusFlag":"(\w+)","statusId":"(\w+)"
So, first I want to check that the value of statusFlag is 'New' or not.
If it is New then I have to proceed and feed statusId in next HTTP request or else display statusFlag mismatch.
Need help. Got stuck badly.
I believe Response Assertion is what you're looking for. Add it after the Regular Expression Extractor and configure it as follows:
Apply to: JMeter Variable -> statusFlag (or your reference name)
Pattern Matching Rules: Equals
Add New as a "Pattern to Test"
The assertion will check whether "statusFlag" is "New" and if not - it will fail the sampler and report the expected and the actual value.
Optionally you can add If Controller after the Response Assertion, use ${JMeterThread.last_sample_ok} as a condition and place 2nd request as a child of the If Controller - it will be executed only if "statusFlag" is new.
See How to Use JMeter Assertions in Three Easy Steps guide for more information on conditionally setting pass or fail criteria to requests in your JMeter test.
That's how your Jmeter project should look like.
Regular Expression Extractor stores extracted value in ct variable that can be accessed in If Controller as "${ct}" == "yourvalue" and, if true, can be also sent as a part of Request 2 body using the same ${ct} reference.
Jmeter project structure

Capture a header value from the response in Jmeter and re-use

I'm calling a REST request for authentication. And I need to get the session ID sending on response; in order to reuse that in my next request.
session id comes in Response header. When I use view result tree, this is not showing header parameters(response body has no data).
When googling I found a method using Regular expression Extractor method, but seems it works only when data in response body.
Nope, Regular expression extractor can search in headers also. You need to specify where to search.
See example,
This will search in headers and you can specify in main samples, sub samples also.

Conditionally sending jmeter variables with HTTP request

I am using JMeter to send HTTP POST requests.
My body of the request is JSON, for example something like {"Var1": "${Var1}","Var2": ${Var2},"Var3":"${Var3}"}.
These are set in the parameters of the HTTP requests with no name for the parameter. This works fine and I am able to send requests using the variables that I set in a beanshell pre processor (by setting the variables and using vars.put() ).
My question is how can I send programmatically through the preprocessor part of the parameters? For example:
if(a){
send parameters `{"Var1": "${Var1}","Var2": ${Var2}` as my JSON
}
else {
send parameters `{"Var3":"${Var3}"}` as my JSON
}
vars.remove() doesn't work for me as it removes the value from the variable but still sends it in the request (for example as "${Var1}").
Replace the preprocessor by a Beanshell Sampler that will compute a boolean value a and put it as a var:
vars.put("a", value)
Then use 2 If Controllers where each one will contain a sampler with the different parameters.
Condition of first one will be ${a} and for be it will be the negation of ${a}.
Just use the "Body Data" tab. You can conditionally create the JSON string and then just "print" the variable in the body data using normal placeholders.
The easiest and fastest way of achieving what you want to do is to use the JMeter if controller (Add -> Logic controller -> If controller).
You add an if controller to the Thread Group that you're working on and place your expression that returns a boolean in Condition (default Javascript). As a child node for the if controller you place the HTTP Request sampler that you want to fire in case the if is successful.
Suppose you want to send a request if a property that you are passing to JMeter exists:
${__P(media)}.length > 0
The you add another if controller with a negated condition for what you just checked with another HTTP Request sampler.
You're done.

Resources