I have thread group with single sampler.I have a scenario with 10 users to run for 1 hour duration. in view results tree showing different response data in every sampler's response data.can it possible to count how many times samplers get same response data.
{"success":false,"code":"104","message":"xx","status":412,"MessageType":"120","ResponseCode":"100","rilreplyDetails":"121"}
{"success":false,"code":"104","message":"yyy","status":412,"MessageType":"120","ResponseCode":"100","rilreplyDetails":"121"}
can I get a count of how many samplers get"xx" response,and how many for "yyy"?
One solution would be to define two variables in the Test Plan section, i.e: counter_xx and counter_yyy.
Then on the sampler request add one Regular Expression Extractor to extract the message value and finally use If Controller to specify which counter to increment.
The below image shows the structure for above solution.
Finally, you would be able to access the variable values by using ${counter_xx} or ${counter_yyy}.
The easiest would be doing this outside of JMeter, i.e. configure it to save response data by adding the next 2 lines to user.properties file:
jmeter.save.saveservice.output_format=xml
jmeter.save.saveservice.response_data=true
JMeter restart will be required to pick the properties up. Once your test is done inspect the resulting .jtl result file using your favorite XML editor.
See Configuring JMeter for more information on the approach.
Another option is using JSR223 Listener and the script like:
import org.apache.jmeter.engine.util.CompoundVariable
import org.apache.jmeter.functions.IterationCounter
def xxcounter = props.get("xxcounter")
if (xxcounter == null) {
xxcounter = new IterationCounter();
List<CompoundVariable> params = new ArrayList<>();
params.add(new CompoundVariable("false"));
xxcounter.setParameters(params);
}
def yycounter = props.get('yycounter')
if (yycounter == null) {
yycounter = new IterationCounter();
List<CompoundVariable> params = new ArrayList<>();
params.add(new CompoundVariable("false"));
yycounter.setParameters(params);
}
if (prev.getResponseDataAsString().contains('xx')) {
log.info('XX count: ' + xxcounter.execute(prev, sampler))
props.put('xxcounter', xxcounter)
}
if (prev.getResponseDataAsString().contains('yyy')) {
log.info('YYY count: ' + yycounter.execute(prev, sampler))
props.put('yycounter', yycounter)
}
The listener will scan current sampler response data and increment either this or that counter printing the current value to jmeter.log file.
Demo:
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It
Related
I am new to jmeter and I am trying run http request 10 times to create 10 categories in a loop
Creating loop to run http request within it
http request
Every time, I store the response(category id) in Json Extractor in a loop.
extract value from response
At the end of the loop, how can I store all the responses (i.e. category IDs) in an array object?
Since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting
Here is some form of Groovy solution:
def ids = vars.get('categoryIDs') ?: []
if (ids instanceof String) {
ids = new groovy.json.JsonSlurper().parseText(ids)
}
ids.add(new groovy.json.JsonSlurper().parse(prev.getResponseData()).id)
vars.put('categoryIDs', new groovy.json.JsonBuilder(ids).toPrettyString())
Demo:
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
I have explored and tried solution mentioned on Google or StackOverflow but could not solve my problem.
I am trying to iterate over each row of CSV and use every column of a row in "HTTP Sampler"
This is what I have tried till now.
My Test plan structure
This is my CSV file
This is my CSV Data Set Config
I am reading entire CSV and storing values in JMeter properties variable using Bean Shell Sampler.
This is the code in Bean Shell Sampler
import java.text.*;
import java.io.*;
String filename = "load_test_date.csv";
ArrayList strList = new ArrayList();
try{
log.info("starting bean shell");
File file = new File(filename);
if(!file.exists()){
throw new Exception ("ERROR: file " + filename + " not found");
}
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String line = null;
log.info("while loop starting");
headerLine = br.readLine();
while((line = br.readLine())!=null){
log.info(line);
String[] variables = line.split(",");
props.put("header_1",variables[0]);
props.put("header_2",variables[1]);
props.put("header_3",variables[2]);
props.put("header_4",variables[3]);
props.put("header_5",variables[4]);
}
}catch(Exception ex){
log.error(ex.getMessage());
}
Now I want to iterate over props variable and fetch each column. I tried using While controller and ForEach Controller, but it is not giving me desired output.
while controller
While loop is executing twice (instead of three times for three rows in csv file) and always using last row values
I used ForEach controller too but could not produce desired outcome
First of all, forget about Beanshell, since JMeter 3.1 you should be using JSR223 Test Elements and Groovy language for scripting.
Second, if I correctly got your point and you want to iterate all the values, i.e. from 1 to 15, you need different approach, for example read the whole file into memory, split each line by comma and create a JMeter Variable for each "cell" value, example Groovy code would be something like:
SampleResult.setIgnore()
def lines = new File('load_test_date.csv').readLines()
def counter = 1
1.upto(lines.size() - 1, { index ->
def line = lines.get(index)
line.split(',').each { column ->
vars.put('value_' + counter, column)
counter++
}
})
if you execute the script and look into Debug Sampler output you will see the following JMeter Variables
In order to iterate the generated variables you can use ForEach Controller configured like:
And use ${value} in the HTTP Request sampler to access the next "cell" value on each iteration:
I need to map my test case with the input data that is present in a csv file and compare it with rest response and generate a responce csv file with that perticular test scenerio in Jmeter.
So I am providing the deviceID as input and validating the json response and writing it into a csv file. for for single occurrence I can get the value as well as I can tag my test case in the response csv file. but when I try with multiple input with multiple test case my response came up returning the last value. like:
Validate County ETR available with No Ticket April16PM Hurricane Event
lets say my input is:
Test Case Device ID Execution
Validate if Active Event 40122480 Yes
Validate if Valid Device ID 277136436 Yes
Validate City ETR available with No Ticket 268698851
Validate County ETR available with No Ticket 18515907
bean shell code is:
scenario = vars.get("ScenarioName");
eventname = vars.get("C_EventName");
eventtype = vars.get("C_EventType");
areaName = vars.get("C_AreaName");
areaType = vars.get("C_AreaType");
f = new FileOutputStream("C:\\RestService\\Result.csv", true); //specify true if you want to overwrite file. Keep blank otherwise.
p = new Print`enter code here`Stream(f);
this.interpreter.setOut(p);
print( scenario + ", " + eventname + ", " + eventtype + ", " + areaName + ", " + areaType);
f.close();
I have increse the number of threads to 4 but the loop count is 1.
can you please help me out. in this JMeter issue
I would not recommend going for Beanshell-based approach as if more than one thread (virtual user) will be writing into the same file the result will be unpredictable and most probably wrong as you are creating the race condition there.
The best option would be adding your variables to .jtl results file directly. To do this:
Add the next line to user.properties file (located in "bin" folder of your JMeter installation
sample_variables=ScenarioName,C_EventName,C_EventType,C_AreaName,C_AreaType
Restart JMeter to pick up the change
Next time you run your JMeter test in command-line non-GUI mode like:
jmeter -n -t test.jmx -l result.jtl
the resulting .jtl file will have 5 extra columns holding the values of the aforementioned variables for each request.
References:
Sample Variables
Configuring JMeter
Results file configuration
I have a CSv Data Set Config which I am using in a while loop. I have this in a module and use this same module several times in my test.
My first problem is that I have set the while loop with this condition:
${__javaScript("${data}"!="<EOF>")}
The "data" being the first column in my csv file. This works fine except for the last iteration where ${data} gets set to "EOF" and has all the tests performed on it. I want it to stop before this, not after all the tests have ran once on it.
My other problem is that when I use this module again later, ${data} is still set to "EOF" and no tests are run at all.
To avoid this <EOF> bit just put your logic under the If Controller and use "${data}" != "<EOF>" as the "Condition"
See Using the While Controller in JMeter guide for detailed explanation of this and other common use cases.
UPD. Reusing the same CSV file:
Add a Beanshell Sampler after 1st While Controller and before the 2nd While Controller and use the following code in "Script" area:
import org.apache.jmeter.services.FileServer;
FileServer.getFileServer().closeFile("yourfile.csv");
vars.put("data", "");
The above script will "close" the original CSV file so it could be reused later on in the script and "clear" ${data} variable as it contains <EOF> value.
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for details on using Beanshell scripts in JMeter tests.
If you would use Loop Controller, with number of CSV lines being number of iterations you could avoid that. Just put this code into Beanshell Sampler:
import org.apache.commons.io.FileUtils;
int lines = FileUtils.readLines(new File("/home/username/csv.file")).size();
vars.put("linesCount", String.valueOf(lines));
After that you can use lineCount in the Loop Controller.
If your data variable needs to be reverted to original state, you could store default value in other variable, and at the end of Loop revert data to it using Beanshell pre/post proccesor.
EDIT:
Or you could insert If Controller in your While Controller and process all child elements only if data doesn't equals EOF:
${__javaScript("${data}"!="<EOF>")}
Neither of the previous suggestions to go and re-use a csv file had worked for me. I ended up doing something different. It's way more complicated than I like, but it works.
I posted my answer to that in another post (https://stackoverflow.com/a/64086009/4832515), but I'll copy & paste it incase that link doesn't work in the future.
I couldn't find a simple solution to this. I ended up using beanshell scripts, which let you use code very similar to java to do some custom stuff. I made an example JMeter project to demonstrate how to do this (yes it's ridiculously complicated, considering all I want to do is repeat the CSV read):
Files:
my file structure:
JMeterExample
|
⊢--JMeterTests.jmx // the JMeter file
⊢--example.csv // the CSV file
contents of my CSV:
guest-id-1,"123 fake street",
guest-id-2,"456 fake street",
guest-id-3,"789 fake street",
so in this thread group, I'm going to just have 1 user, and I'll loop 2 times. I intend to send 1 request per CSV line. So there should be 6 requests sent total.
Thread Group
User Defined Variables
This is kind of optional, but the filepath is subject to change, and I don't like changing my scripts just for a change in configuration. So I store the CSV filename in a "User Defined Variables" node.
If you are storing the CSV file in the same directory as your JMeter test, you can just specify the filename only.
If you are saving the CSV in a folder other than the directory containing your JMeter file, you will need to supply an absolute path, and then slightly modify the beanshell script below: you'll need to comment out the line that loads the file relatively, and comment in the line that loads from an absolute path.
BeanShell Sampler to parse and store CSV lines
Add a Beanshell Sampler which will basically take in a path, and parse & store each line as a variable. The first line will be stored as a variable called csv_line_0, the 2nd line will be csv_line_1 and so on. I know it's not a clean solution but... I can't find any clean simple way of doing this clean simple task. I copied and pasted my code below.
import org.apache.jmeter.services.FileServer;
import java.text.*;
import java.io.*;
import java.util.*;
String temp = null;
ArrayList lines = new ArrayList();
BufferedReader bufRdr;
ArrayList strList = new ArrayList();
// get the file
try {
// you can use this line below if your csvFilePath is an absolute path
// File file = new File(${csvFilePath});
// you can use this line below if your csvFilepath is a relative path, relative to where you saved this JMeter file
File file = new File(org.apache.jmeter.services.FileServer.getFileServer().getBaseDir() + "/" + ${csvFilePath});
if (!file.exists()) {
throw new Exception ("ERROR: file " + filename + " not found");
}
bufRdr = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
} catch(Exception e){
log.error("failed to load file");
log.error(e.getMessage());
return;
}
// For each CSV line, save it to a variable
int counter = 0;
while(true){
try{
temp = bufRdr.readLine();
if(temp == null || temp.equals("<EOF>")){
break;
}
lines.add(temp);
vars.put("csv_line_" + String.valueOf(counter), temp);
counter++;
} catch(Exception e){
log.error("failed to get next line");
log.error(e.getMessage());
break;
}
}
// store the number of CSV lines there are for the loop counter
vars.put("linesCount", String.valueOf(lines.size()));
Loop Controller
Add a Loop Controller that loops once for each CSV line. ${linesCount} is a count of the number of CSV lines and is calculated from the above beanShell script.
Beanshell script to extract data from current CSV Line
This script will run once per CSV line. It will go and grab the current line, and parse out whatever data is on it. You'll have to modify this script to get the data you want. In my example, I only had 2 columns, where column 1 is a "guestId", and column 2 is an "address".
__jm__loopController__idx is a variable JMeter defines for you, and is the index of the loop controller. The variable name is __jm__{loop controller name}__idx.
String index = vars.get("__jm__loopController__idx");
String line = vars.get("csv_line_" + index);
String [] tokens = line.split(",");
vars.put("guestId", tokens[0]);
vars.put("address", tokens[1]);
Http request sampler
Here's the HTTP request that's using the data extracted.
result
When running this, as desired, I end up sending 6 http requests over to the endpoint I defined.
I'm landing into a page where some Customers listed out. I'm retriving all the Customer Ids by Regular Expression Extractor Post-Processor.
Now, in a subsequent request I need to pass those Ids. It's being passed as a 'Body Data' by the following format:
[19327,15947,14421,18813,20942]
Let say, there are 5 Customer Ids retrived, then I can use the variables for each record as follows:
Passing Variables: [${CustomerId_1},${CustomerId_2},${CustomerId_3},${CustomerId_5}]
Posting Variable Values: [19327,15947,14421,18813,20942]
But let say, there are only 3 Customer Ids retrived, and if I pass the variables as above then the sampler will fail because currently it just retrived 3 Customer Id records.
Passing Variables: [${CustomerId_1},${CustomerId_2},${CustomerId_3},${CustomerId_5}]
Posting Variable Values: [19327,15947,14421,${CustomerId_4},${CustomerId_5}]
How to deal with this issue, plz. do help.
Thanks in advance
Add Beanshell PreProcessor as a child of your 2nd request
Put the following code into the Pre-Processor's "Script" area
int customers = Integer.parseInt(vars.get("CustomerId_matchNr"));
StringBuilder requestBuilder = new StringBuilder();
requestBuilder.append("[");
for (int i = 1; i <= customers; i++) {
requestBuilder.append(vars.get("CustomerId_" + i));
if (i != customers) {
requestBuilder.append(",");
}
}
requestBuilder.append("]");
sampler.getArguments().getArgument(0).setValue(requestBuilder.toString());
The above code will build required request line depending on number of matches and automatically set request body.
Referenced classes:
vars - shorthand to JMeterVariables
sampler - provides access to the parent sampler, in case of HTTP Request it will be HTTPSamplerProxy
StringBuilder - comes with Java SDK
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on Beanshell scripting, explanation of pre-defined variables and some useful examples.
refName_matchNr will return the number of matches. So in your case CustomerId_matchNr will give you number of customerIDs.
Use a beanshell pre-processor to run a loop and construct the BodyData string and save it to a new variable, use that variable in your subsequent sampler.