In my JMeter test plan, i have 3 transaction controllers.
I want to extract the transaction controller name and pass it to the Jmeter script.
I am unable to extract the transaction controller name, which is displayed into "Log viewer Panel".
To print transaction name , i have used BeanShell Listener, with following code :
String tname= sampleResult.toString();
if(tname.startsWith("T01_Login"))
{
log.info("*Transaction Name = " +sampleResult.toString() + " - Response time = " + sampleResult.getTime());
String temp = sampleResult.toString();
String temp2 = sampleResult.getTime().toString();
vars.put("Transaction_Name",temp);
vars.put("Response", temp2);
log.info(vars.get("Response"));
log.info(vars.get("Transaction_Name"));
}
I have used BSF post processor to store/extract the transaction name, by using following code:
Language selected in : Javascript
var transact = ${Transaction_Name};
vars.put ("TRANSACT",transact);
log.info(TRANSACT);
When checked into LogViewer panel, following text is displayed:
2017/03/27 17:06:13 INFO - jmeter.util.BeanShellTestElement: *Transaction Name = T01_Login - Response time = 39829
2017/03/27 17:06:13 INFO - jmeter.util.BeanShellTestElement: 39829
2017/03/27 17:06:13 INFO - jmeter.util.BeanShellTestElement: T01_Login
Kindly provide your valuable suggestion on this.
To resolve the error which prevents post-processor from running, use vars.get, instead of var transact = ${Transaction_Name};, i.e.
var transact = vars.get("Transaction_Name");
And setting another variable (vars.put ("TRANSACT",transact);) is unnecessary: just use Transaction_Name. (And another small note: BSF set of objects is now deprecated, so switch them to either JSR322 or BeanShell)
But it will not work anyways, because the order of execution is
Sampler > Post-processor > Listener > Transaction Controller > Listener
So the value of Transaction_Name inside post-processor will either be empty (on first iteration), or will be coming from previous iteration, which I guess is not what you want.
You don't mention your use case, but some options you have are:
Have a special sampler AFTER transaction controller to do what you wanted in that post-processor. For example:
Transaction Controller
Some Sampler
...
JSR223 / Beanshell sampler
This second sampler can obtain proper transaction name, since it's running after the transaction
Save transaction name into variable before calling a transaction. Set transaction controller name to that variable:
JSR223 / Beanshell sampler
sets variable: vars.put("Transaction_Name", "T01_Login");
${Transaction_Name} <-- this is the name of the transaction controller
Sampler
Post-processor <-- here the Transaction_Name can be obtained.
Related
I was using JMeter properties for storing the threadLocalCachedConnection object. I made sure to use unique property names as properties.
In thread group 1, I had a JSR223 PostProcessor to scrape session per thread(VU), and then store it in a property called sessionID.
And I added another JSR223 PostProcessor as a child of the last sampler in the Thread Group1.
def connection = sampler.threadLocalCachedConnection
props.put("presenterConnection" + ctx.getThreadNum(), connection.get())
In Thread Group 2, I added a JSR223 PreProcessor as a child of the first sampler.
def presenterConnection = props.get('presenterConnection' + ctx.getThreadNum())
sampler.threadLocalCachedConnection.set(presenterConnection)
String sendCommand = "SEND\n" +
"content-type:application/json;charset=UTF-8\n" +
"destination:/v1/session/${__property(sessionId)}/command\n" +
"id:perftest01-presenter-${__property(sessionId)}\n" +
"\n" +
"{\"type\": \"go-to-slide\", \"data\": {\"index\": 0}}\n" +
'\0' // note: NULL char at end
;
vars.put("wsStompSendCommand", sendCommand);
I tested with 2 threads (VUs). Why both threads were using the last sessionId instead of using one sessionId per thread??
As per JMeter Documentation:
Properties are not the same as variables. Variables are local to a thread; properties are common to all threads
so your line
props.put('sessionId', vars.get('sessionUUID'))
creates a global sessionId propety which is:
common for all Threads no matter in which Thread Group they are
exists until you shut down JMeter/JVM
You need to play the same trick as with the presenterConnection to wit:
props.put('sessionId_'+ ctx.getThreadNum(), vars.get('sessionUUID'))
and then read it where required:
def sessionId = props.get('sessionId_'+ ctx.getThreadNum())
More information: Apache Groovy: What Is Groovy Used For?
In Message body, I want to display content like
Threads : 1
Rampup : 1
Loop : 2
Duration : 10 seconds
How could we print all the properties of thread in mail body?
You can get the values dynamically in the runtime by calling the relevant JMeterContext class methods from the __groovy() function like:
Threads: ${__groovy(ctx.getThreadGroup().getPropertyAsString('ThreadGroup.num_threads'),)}
Ramp Up: ${__groovy(ctx.getThreadGroup().getPropertyAsString('ThreadGroup.ramp_time'),)}
Loops: ${__groovy(ctx.getThreadGroup().getSamplerController().getPropertyAsString('LoopController.loops'),)}
Demo:
Assuming the following Thread Group definition:
You can get the required information with __groovy() function:
The function can be used literally anywhere in your script, for example in the SMTP Samplers message input field
You can enter text and JMeter Variables in to message body:
Add SMTP Sampler
Set up email settings: mail server host, port, login, password,..
Set up message body, use text and variables, for example:
Thread: ${__threadNum}.
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 can I get an overall PASS/FAIL result for a JMeter thread group without using a post processor on every sampler?
I've tried using a beanshell listener, but it doesn't work for instances where there are multiple samplers inside a transaction controller with "Generate Parent Sample" enabled. In that case, the listener only gets called once per transaction controller and I'm only able to access the result of the last sampler inside the transaction controller.
Edit:
I would like to be able to save a pass/fail value as Jmeter variable or property for the thread group. If one or more components of the thread group fail or return an error, then that would be an overall fail. This variable will then be used for reporting purposes.
My current beanshell listener code:
SampleResult sr = ctx.getPreviousResult();
log.info(Boolean.toString(sr.isSuccessful()));
if (!sr.isSuccessful()){
props.put("testPlanResult", "FAIL");
testPlanResultComment = props.get("testPlanResultComment");
if(testPlanResultComment == ""){
testPlanResultComment = sr.getSampleLabel();
}else {
testPlanResultComment = testPlanResultComment + ", " + sr.getSampleLabel();
}
props.put("testPlanResultComment", testPlanResultComment);
log.info(testPlanResultComment);
}
If you call prev.getParent() you will be able to fetch individual sub-samples via getSubResults() function, something like:
prev.getParent().getSubResults().each {result ->
log.info('Sampler: ' + result.getSampleLabel() + ' Elapsed time: ' + result.getTime() )
}
log.info('Total: ' + prev.getParent().getTime())
Demo:
More information: Apache Groovy - Why and How You Should Use It
JMeter Version 2.13 r1665067
So I seem to be having some trouble when using User-Defined Variables and/or JMeter Property Variables inside a CookieManager.
If I use a variable as the value for a Cookie inside the CookieManager, whether or not it's a User-Defined Var or a Property Var I have the same problem when trying to view the Cookie's value(s) inside a BeanShell Pre and PostProcessor.
If my Cookie Manager has this below: *The 1st line is when using properties variable and 2nd line is when using a var from a User Defined Variable, *FYI both lines are NOT used at the same time:
CookieManager:
NAME VALUE DOMAIN PATH
1st) MYID ${__P(propCookie)} www.mydomain.com /
OR
2nd) MYID ${userCookie} www.mydomain.com /
The propCookie variable is passed on the CLI or defined in a .properties file like below:
COMMAND-LINE --> -JpropCookie=SRV1
IN PROP FILE --> propCookie=SRV1
And the userCookie variable is defined inside a User Defined Variables Config Element like so:
NAME VALUE DESCRIPTION
userCookie ${__P(propCookie)} User var using prop variable as value
Then, when I run my test I can see in the Request Tab of the Results Tree that it is showing the Cookie and it has the correct value assigned to it, which is good... But when I attempt to view the Cookies in a BeanShell Pre/Post-Processor, it simply shows the Variable and NOT the actual value.
BeanShell PreProcessor Code
import org.apache.jmeter.protocol.http.control.Cookie;
import org.apache.jmeter.protocol.http.control.CookieManager;
log.info("### Inside BeanShell PreProcessor:");
CookieManager manager = sampler.getCookieManager();
log.info("Cookie Count = '" + manager.getCookieCount() + "'");
for (int i = 0; i < manager.getCookieCount(); i++) {
Cookie cookie = manager.get(i);
log.info("\t\t Cookie.getName() = '" + cookie.getName() + "'");
log.info("\t\t Cookie.getValue() = '" + cookie.getValue() + "'");
}
Here is the BeanShell Script's Output in the Log:
2015/04/29 14:33:00 INFO - jmeter.util.BeanShellTestElement: ### Inside BeanShell PreProcessor:
2015/04/29 14:45:58 INFO - jmeter.util.BeanShellTestElement: Cookie Count = '1'
2015/04/29 14:33:00 INFO - jmeter.util.BeanShellTestElement: Cookie.getName() = 'MYID'
2015/04/29 14:33:00 INFO - jmeter.util.BeanShellTestElement: Cookie.getValue() = '${userCookie}'
So as you can see in the output from the BeanShell, the getValue() function is printing the Variable assigned to the Cookie's value exactly like this --> "${userCookie}", and NOT what the actual Cookie's value is, which is "SRV1"...
Lastly, if I try to use the "COOKIE_" variable which is supposed to get automatically created, and I use this in BeanShell, vars.get("COOKIE_MYID"), it prints "null" every time... I have all the proper Cookie properties set in the jmeter.properties file, like these here, so I'm not sure what the problem is:
CookieManager.allow_variable_cookies=true
CookieManager.save.cookies=true
CookieManager.name.prefix=COOKIE_
I'm pretty much stumped for why this is happening so if anyone has any ideas for why this is happening, please feel free it would be greatly appreciated!
Thanks in Advance,
Matt
HTTP Request Sampler actually sets the cookie using CookieManager's getCookieHeaderForURL method which substitutes the value properly.
In Beanshell,
import org.apache.jmeter.protocol.http.control.Cookie;
import org.apache.jmeter.protocol.http.control.CookieManager;
manager = sampler.getCookieManager();
log.info(manager.getCookieHeaderForURL(new URL("http://www.google.com"))); //update the URL
This gives the cookies with updated values.
CookieManager's get & add methods are used to get & add cookies to the HTTP Cookie Manager at run time. So, getValue method gives the value as it is. getCookieHeaderForURL gets the appropriate cookies from the Cookie Manager for the domain with updated values.