My requirement is to write two values using 2 Beanshell Samplers used in different steps, in a single line and separated by a comma
But the second variable is written on a new line
I have two different Beanshell Samplers at different steps.
First one captures Variable 1 and writes it in a file
Second one captures Variable 2 and writes it in the file
First Code:
String path= FileServer.getFileServer().getBaseDir() + "//P_IssuePolicy.txt";
SubmissionNum= vars.get("CP_SubmissionNumber");
EMailID= vars.get("P_emailID");
f = new FileOutputStream(path, true);
p = new PrintStream(f);
this.interpreter.setOut(p);
p.println(EMailID+","+SubmissionNum);
f.close();
Second Code:
String path= FileServer.getFileServer().getBaseDir() + "//P_IssuePolicy.txt";
Policynumber= vars.get("CP_Policynumber");
f = new FileOutputStream(path, true);
p = new PrintStream(f);
this.interpreter.setOut(p);
p.println(","+Policynumber);
f.close();
Expected Result:
abc#email.com,12345601,12345602
Actual Result:
abc#email.com,12345601
,12345602
Instead of println which adds new line use print
p.print(EMailID+","+SubmissionNum);
String path= FileServer.getFileServer().getBaseDir() + "//P_IssuePolicy.txt";
SubmissionNum= vars.get("CP_SubmissionNumber");
EMailID= vars.get("P_emailID");
Policynumber= vars.get("CP_Policynumber");
f = new FileOutputStream(path, true);
p = new PrintStream(f);
this.interpreter.setOut(p);
p.println(EMailID+","+SubmissionNum+","+Policynumber);
f.close();
Give it a try with above.
First of all, are you aware of Sample Variables property and Flexible File Writer? If you run your script with multiple virtual users most probably you will suffer from a form of a race condition when multiple threads will be simultaneously writing into the same file resulting in garbage data
Since JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language for any scripting tasks, the reasons are in:
Groovy is compatible with modern Java versions and with Beanshell you're stuck at Java 5 language level
Groovy has much better performance than Beanshell
Groovy has a lot of enhancements making your life easier
For example your code can be shortened as:
First:
def file = new File(org.apache.jmeter.services.FileServer.getFileServer().getBaseDir() + "//P_IssuePolicy.txt")
file << vars.get("P_emailID") << "," << vars.get("CP_SubmissionNumber") << ","
Second:
def file = new File(org.apache.jmeter.services.FileServer.getFileServer().getBaseDir() + "//P_IssuePolicy.txt")
file << vars.get("CP_Policynumber") << System.getProperty("line.separator")
Related
import java.io.*;
import com.opencsv.CSVWriter;
File f= new File("C:\\Users\\Web\\Desktop\\Tokenss.csv");
FileWriter fw= new FileWriter(f);
BufferedWriter bw= new BufferedWriter(fw);
//var rc = prev.getResponseCode();
//ctx.getPreviousResult().getResponseHeaders();
String tok = vars.get("Token");
bw.write(tok);
bw.newLine();
bw.close();
fw.close();
Question: how to write access_token in CSV always in a new row? It overwrites my access token every time.
You're overwriting the whole file each time you call your script, in order to write new line at the end of the file you need change this:
FileWriter fw= new FileWriter(f);
to this:
FileWriter fw= new FileWriter(f, true);
where second argument is the switch for the "append" mode
In general since JMeter 3.1 you should be using JSR223 Test Elements and Groovy language so consider migrating to Groovy on next available opportunity. You will either be able to re-use your existing code or simplify it to something like:
new File('C:\\Users\\Web\\Desktop\\Tokenss.csv') << vars.get('Token') << System.getProperty('line.separator')
See Apache Groovy - Why and How You Should Use It article for more information on Groovy scripting in JMeter
I have a test plan, where i have two thread groups, first thread group will run and will log the result into a file, the logged file will be the input to the second thread group.
Now, for doing this in thread group one i added BeanShell PostProcessor script as follows, but it works as follows
open jmeter and run the test plan (log file "testing.csv" will be created as fresh)
For first time "isHeaderWritten" property is false.
No without closing and reopening the jmeter, run the script again. i expect the log file "testing.csv" must be truncated and add the values freshly. But what acually happening is "testing.csv" file is appended with the new values.
Now, close the jmeter and open again, this time log file "testing.csv" will be truncated and fresh new values are added.
How to clear the file and re-write the records for each run (without closing the jemeter)
import org.apache.jmeter.util.JMeterUtils;
threadName=ctx.getThread().getThreadName();
log.info("threadName: "+threadName);
isHeaderWritten = JMeterUtils.getPropDefault("isHeaderWritten","false");
fileName="C:\\response\\testing.csv";
log.info("isHeaderWritten: "+isHeaderWritten);
if(isHeaderWritten == "true"){
f = new FileOutputStream(fileName, true);
fileHeader = "requestStatus,cNumber,pId,id,token";
}else{
log.error("isHeaderWritten:"+isHeaderWritten);
f = new FileOutputStream(fileName, false);
fileHeader = "requestStatus,cNumber,pId,id,token";
}
p = new PrintStream(f);
this.interpreter.setOut(p);
if(isHeaderWritten == "false"){
print(fileHeader);
JMeterUtils.setProperty("isHeaderWritten", "true");
}
log.info("Test results will be written to file "+fileName);
cNumber=vars.get("cNumber");
log.info("cNumber"+cNumber);
pId = vars.get("pId");
log.info("pId"+pId);
pmId = vars.get("pmId");
log.info("pmId"+pmId);
tTxt = vars.get("tTxt");
log.info("tTxt"+tTxt);
responseCode=prev.getResponseCode();
log.info("responseCode of "+requestString+ " is "+responseCode);
requestStatus = "Success";
if(!"201".equals(responseCode)){
requestStatus = "Failure"+","+cNumber+","+pId+","+pmId+","+tTxt;
}
result = requestStatus;
if("Success".equals(requestStatus)){
responseData=new String(data);
log.info("responseData of "+requestString+ " is "+responseData);
requestString=requestStatus+","+cNumber+","+pId+","+pmId+","+tTxt;
result = requestString;
log.info("result"+result);
}
log.debug(result);
print(result);
f.close();
According to JMeter Documentation:
Properties are global to JMeter, so can be used to communicate between threads and thread groups
Properties are not the same as variables. Variables are local to a thread; properties are common to all threads
So once you execute this line:
JMeterUtils.setProperty("isHeaderWritten", "true");
the property isHeaderWritten will become true and will remain true until you restart JMeter.
The easiest solution would be adding a tearDown Thread Group to your test plan (this Thread Group is being executed after any other thread group(s)) and add a JSR223 Sampler with the following code:
SampleResult.setIgnore();
org.apache.jmeter.util.JMeterUtils.setProperty("isHeaderWritten", "false");
Since JMeter 3.1 users are encouraged to switch to JSR223 Test Elements and Groovy language for any form of scripting mainly because Groovy performance is much better than Beanshell so consider migrating to JSR223 PostProcessor and Groovy language on next available opportunity
I am trying to duplicate a file using JMeter,
The scenario:
Loading a JSON file. For example, {"name":"John","age":"$age_place"}
Modify one property - age_place from 1 to 20
Save each modified iteration into a separate file
I have tried to do that with Simple Data Writer but it didn't work.
You have JSR223 Elements as Sampler or Pre processor which you can add powerful script,
The easiest is to replace age_place with your value, for example if saved in variable age_place:
f = new FileOutputStream("c:\\temp\\template.json", false);
p = new PrintStream(f);
this.interpreter.setOut(p);
print("{\"name\":\"John\",\"age\":\"age_place\"}".replaceAll("age_place", vars.get("age_place")));
f.close();
If you need to generate 20 files with different age you can do it using any of JSR223 Test Elements. Example Groovy code would look like:
def json = new groovy.json.JsonSlurper().parseText("{\"name\":\"John\",\"age\":\"\"}")
def builder = new groovy.json.JsonBuilder(json)
1.upto(20, {
builder.content.age= "${it}"
def writer = new File('file' + "${it}" + ".json").newWriter()
writer << builder.toPrettyString()
writer.close()
})
Once you execute your test it will create the following files in the "bin" folder of your JMeter installation:
file1.json - with the age of 1
file2.json - with the age of 2
...
file20.json - with the age of 20
References:
Groovy For Loop Examples
Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
I have a selenium script which is running in Jmeter using JUnit sampler. My selenium program has a few system.pritnln statements which I see it in console when Jmeter runs, how can I write them to a file?
I would go for Sample Variables instead so you could get Username included into .jtl results file, add the code like:
In JUnit:
JUnitSampler sampler = new JUnitSampler();
JMeterVariables vars = sampler.getThreadContext().getVariables();
vars.put("username", your_username_variable);
vars.put("elapsed", your_total_time_variable);
sampler.getThreadContext().setVariables(vars);
In JMeter's user.properties file:
sample_variables=username,elapsed
If you want a separate file - just replace all your System.out.println(""); with:
FileUtils.writeStringToFile(new File("/path/to/file"),"what you need to write", true);
See How to Use JUnit With JMeter article for more information on running your JUnit tests with JMeter
If you do not want to create a separate file and you can use log file then below statement will do to write in a log file
log.info(" TEXT ");
If you want to create a separate file, then
import org.apache.jmeter.services.FileServer;
f = new FileOutputStream("c:/output/result.txt", true);
p = new PrintStream(f);
p.println(" Hello World "); // update here what you want to write
p.close();
f.close();
1: Add JSR223 Sampler to yoour test plan
2: Write below code:
FileWriter fstream = new FileWriter("D:\\subid.csv",true); //Create New file with name "subid"
BufferedWriter out = new BufferedWriter(fstream);
out.write(vars.get("variable1"));//write value of variable 1
out.write(",");
out.write(vars.get("variable2"));//write value of variable 2
out.write(System.getProperty("line.separator"));//insert new line
out.close();
fstream.close();
I have created a JMeter functional test that essentially:
creates a user;
logs in with the user;
deletes the user.
Now, I need to be able to thread this, and dynamically generate a username with a default prefix and a numerically incremented suffix (ie TestUser_1, TestUser_2, ... etc).
I used the counter, and things were working fine until I really punched up the number of threads/loops. When I did this, I was getting a conflict with the counter. Some threads were trying to read the counter, but the counter had already been incremented by another thread. This resulted in trying to delete a thread that was just created, then trying to log in with a thread that was just deleted.
The project is set up like this:
Test Plan
Thread group
Counter
User Defined Variables
Samplers
I was hoping to solve this problem by using the counter to append a number to the user defined variables upon thread execution, but the counter cannot be accessed in the user defined variables.
Any ideas on how I can solve this problem?
Thank you in advance.
I've used the following scheme successfully with any amount of test users:
1. Generate using beanshell-script (in BeanShell Sampler e.g.) csv-file with test-user details, for example:
testUserName001,testPwd001
testUserName002,testPwd002
. . .
testUserName00N,testPwd00N
with the amount of entries you need for the test-run.
This is done once per "N users test-run", in separate Thread Group, in setUp Thread Group or maybe even in separate jmx-script... makes no difference.
You can please find working beanshell-code below.
2. Create your test users IN TEST APPLICATION using previously created users-list.
If you don't need create in application you may skip this.
Thread Group
Number of Threads = 1
Loop Count = 1
. . .
While Controller
Condition = ${__javaScript("${newUserName}"!="",)} // this will repeat until EOF
CSV Data Set Config
Filename = ${__property(user.dir)}${__BeanShell(File.separator,)}${__P(users-list,)} // path to generated users-list
Variable Names = newUserName,newUserPwd // these are test-users details read from file into pointed variables
Delimiter = '
Recycle on EOF? = False
Stop thread on EOF? = True
Sharing Mode = Current thread group
[CREATE TEST USERS LOGIC HERE] // here are actions to create separate user in application
. . .
3. Perform multi-user logic.
Schema like the given above one but Thread Group executed not for 1 but for N threads.
Thread Group
Number of Threads = ${__P(usersCount,)} // set number of users you need to test
Ramp-Up Period = ${__P(rampUpPeriod,)}
Loop Count = X
. . .
While Controller
Condition = ${__javaScript("${newUserName}"!="",)} // this will repeat until EOF
CSV Data Set Config
Filename = ${__property(user.dir)}${__BeanShell(File.separator,)}${__P(users-list,)} // path to generated users-list
Variable Names = newUserName,newUserPwd // these are test-users details read from file into pointed variables
Delimiter = '
Recycle on EOF? = False
Stop thread on EOF? = True
Sharing Mode = Current thread group
[TEST LOGIC HERE] // here are test actions
. . .
The key idea is in using Thread Group + While Controller + CSV Data Set Config combination:
3.1. CSV Data Set Config reads details for each the test users from generated file:
. . . a. only once - because of "Stop thread on EOF? = True";
. . . b. doesn't block file for further access (in another thread groups, e.g., if there are any) - because of "Sharing Mode = Current thread group";
. . . c. pointed variables - "Variable Names = newUserName,newUserPwd" - you will use in further test-actions;
3.2. While Controller forces CSV Data Set Config to read all the entries from generated file - because of defined condition (until the EOF).
3.3. Thread Group will start all the threads with defined ramp-up - or simultaneously if ramp-up = 0.
You can take here template script for described schema: multiuser.jmx.
Beanshell script to generate test-users details looks like below and takes the following args:
- test-users count
- test-user name template ("TestUser_" in your case)
- test-user name format (e.g. 0 - to get TestUser_1, 00 - to get TestUser_01, 000- for TestUser_001, etc... you can simply hardcode this orexclude at all)
- name of generated file.
import java.text.*;
import java.io.*;
import java.util.*;
String [] params = Parameters.split(",");
int count = Integer.valueOf(params[0]);
String testName = params[1];
String nameFormat = params[2];
String usersList = params[3];
StringBuilder contents = new StringBuilder();
try {
DecimalFormat formatter = new DecimalFormat(nameFormat);
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + File.separator + usersList);
for (int i = 1; i <= count; i++) {
String s = formatter.format(i);
String testUser = testName + s;
contents.append(testUser).append(",").append(testUser);
if (i < count) {
contents.append("\n");
}
}
byte [] buffer = contents.toString().getBytes();
fos.write(buffer);
fos.close();
}
catch (Exception ex) {
IsSuccess = false;
log.error(ex.getMessage());
System.err.println(ex.getMessage());
}
catch (Throwable thex) {
System.err.println(thex.getMessage());
}
All together it will look like:
Sorry if answer is too overloaded.
Hope this helps.
The "User Defined Variables" config element does not pick up the reference variable from the "Counter" config element. I think this is a bug in JMeter. I have verified this behavior in version 3.2.
I added a "BeanShell Sampler" element to work around the issue.
Notice that the reference name of the "Counter" element is INDEX
The RUN_FOLDER variable gets set to a combination of the TESTS_FOLDER variable and the INDEX variable in the "BeanShell Sampler"
The "Debug Sampler" simply gathers a snapshot of the variables so I can see them in the "View Results Tree" listener element. Notice how the RUN_FOLDER variable has the INDEX variable value (5 in this case) appended.