my access token is getting overwritten every time - jmeter

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

Related

Files are overwriting instated of appending in BeanShell PostProcessor Jmeter while running 1000 threads

I have written below code under beanshall post-processor. But when I am running 1000 threads the files are overwriting existing content instated of appending. It is working for 1-5 threads. Can anyone help me on this?
import org.apache.commons.io.FileUtils;
import java.util.ArrayList;
import java.util.Collections;
File fExceptionLog = new File("${logPath}/ExceptionLog.txt");
String extExceptionData= FileUtils.readFileToString(fExceptionLog);
id=vars.get("id");
try{
String cDatestamp="${__time(yyyyMMddHHmmssSSS)}";
String cResponce = prev.getResponseDataAsString();
String cRequest = prev.getQueryString();
String cResponceCode=prev.getResponseCode();
cTransactionName = prev.getSampleLabel();
cResponseTime = prev.getTime();
cSize = prev.getBytesAsLong();
cIsSuccessful =prev.isSuccessful();
File fRequestLog = new File("${logPath}/RequestLog.txt");
File fHitLog = new File("${logPath}/HitLog.txt");
File fResponceLog = new File("${logPath}/ResponceLog.txt");
File fErrorLog = new File("${logPath}/ErrorLog.txt");
String extHitData = FileUtils.readFileToString(fHitLog);
String extRequestData = FileUtils.readFileToString(fRequestLog);
String extResponceData = FileUtils.readFileToString(fResponceLog);
String extErrorData = FileUtils.readFileToString(fErrorLog);
log.info("cResponceCode"+cResponceCode);
FileUtils.writeStringToFile(fHitLog,extHitData+id+"~"+cDatestamp+"~"+cTransactionName+"~"+cResponceCode+"~"+cResponseTime+"~"+cSize+"~"+cIsSuccessful+"\n");
if(cResponceCode.equals("200")){
FileUtils.writeStringToFile(fRequestLog,extRequestData+id+"~"+cDatestamp+"~"+cTransactionName+"~"+cResponce+"\n");
FileUtils.writeStringToFile(fResponceLog,extResponceData+id+"~"+cDatestamp+"~"+cResponceCode+"~"+cResponce+"\n");
}else{
FileUtils.writeStringToFile(fErrorLog,extErrorData+id+"~"+cDatestamp+"~"+cTransactionName+"~"+cResponce+"\n"+id+"~"+cDatestamp+"~"+cResponceCode+"~"+cResponce+"\n");
}
}catch(Exception e){
FileUtils.writeStringToFile(fExceptionLog,extExceptionData+id+"~"+cDatestamp+"~"+cTransactionName+"~"+e+"\n");
}
You're violating at least 3 JMeter Best Practices
You're referring JMeter Variables like ${logPath} while you should be using vars shorthand instead like vars.get("logPath")
You're using Beanshell while starting from JMeter 3.1 you should be using JSR223 and Groovy
And last but not the least, you yourself introduced a race condition so when several threads will be concurrently writing the same file it will result in data loss. You can put this Beanshell test element (along with the parent Sampler(s)) under the Critical Section Controller, but it will reduce concurrency of the parent sampler(s) to only one at a time
If you need to write some some metrics into a custom file in your own format I would rather recommend consider migrating to the Flexible File Writer which is extremely "flexible" with regards to what values is to store and it accumulates multiple entries in memory and flushes them periodically in batch manner so all the data will be stored without collisions.
You can install Flexible File Writer using JMeter Plugins Manager

Jmeter clear resultFile for each run

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

How to Duplicate file using JMeter

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

How to use java program in bean pre-processor

The below program reads the XML file and compress into gzip.
I have a couple of questions here.
Can I use the following program directly in JMeter BeanShell pre-processor?
I want to use the output variable as input to JSON request. Is it possible in Jmeter?
Screen shot and details will be appreciated.
public static void main(String[] args) throws Exception {
String line = null;
String sb = "";
File f=new File("D:\\RetailTransactionLog_9419_001_590.xml");
FileReader fr=new FileReader(f);
BufferedReader br=new BufferedReader(fr);
while((line=br.readLine())!=null)
{
sb= sb + line;
}
br.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
gzos.write(sb.getBytes("UTF-8"));
gzos.close();
String base64CompressedString = Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(base64CompressedString);
Of course, you can put your piece of java code directly in a JMeter BeanShell pre-processor and much more !
Insert you pre-processor component as child of your JSON request (as in my script example in attachment).
You don’t need to import java.io package like BufferedReader, ByteArrayOutputStream, File, FileReader, IOException, Base64…
Remove also the main signature public static void main(String[] args) …
You only have to import "java.util.zip.GZIPOutputStream" (A)
I’ve also replace your System.out.println(base64CompressedString) by log.info(base64CompressedString) just to visualize in the jmeter console your output (B)…
And finally add at the end, the code (C) to reference your result in the variable of your choice ("a" in my example).
You just have to call your variable after with ${a} in your json request like in my JMX script :
Unzip attachments http://uplea.com/dl/9F734367B43FB93 :
"ReadAndCompressMyFile.jmx" under /bin and put "test.xml" under C: or change the path in your code.
I’ve used a dummy sampler instead of your json request.
After running my script, you can see in View Result Tree (Request tab) and in the console, the value of "a" (corresponding to base64CompressedString).
PS : To run my script with the "dummy sampler", you need to add jmeter-plugins-dummy-0.1.jar under /lib/ext of your jmeter directory.
Hope to help you...
GZIP compression is rather "heavy" operation, if you will have lots of virtual users - it may become a bottleneck so consider using other approaches:
There is __base64Encode() function available via JMeter plugins
If for any reason it is not enough - go for JSR223 Sampler and Groovy language, Groovy is mostly compatible with Java so your code should work fine (just remove main method)

Jmeter write out to a file

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();

Resources