I wanted to use the same set of headers in multiple jmx files. So I wanted to initialise it once and have to use it across my jmx files.
Can anyone help me in meeting my requirement? Thanks in advance.
That’s not possible.
To be able to apply a Header Manager to all plan, it should have the largest scope but using Include or Module controller means reduced scope.
Thanks to scope stil, you can set your Header Manager as child of test plan and it will apply to whole requests.
You could use properties and __P function to make those configurable in user.properties
You can do this as follows:
Create a CSV file called headers.csv to hold your headers like:
header-1-name,header-1-value
header-2-name,header-2-value
and store it in "bin" folder of your JMeter installation
Add empty HTTP Header Manager to the top level of your Test Plan
Add setUp Thread Group to your Test Plan
Add JSR223 Sampler to the setUp Thread Group
Put the following code into "Script" area:
import org.apache.jmeter.protocol.http.control.Header
import org.apache.jmeter.protocol.http.control.HeaderManager
import org.apache.jmeter.threads.JMeterContext
import org.apache.jmeter.threads.JMeterContextService
import org.apache.jorphan.collections.SearchByClass
SampleResult.setIgnore()
def engine = ctx.getEngine()
def testPlanTree = org.apache.commons.lang3.reflect.FieldUtils.readDeclaredField(engine, "test", true)
def headerManagerSearch = new SearchByClass<>(HeaderManager.class)
testPlanTree.traverse(headerManagerSearch)
def headerManagers = headerManagerSearch.getSearchResults()
headerManagers.any { headerManager ->
new File('headers.csv').readLines().each { line ->
def values = line.split(',')
headerManager.add(new Header(values[0], values[1]))
}
}
If you want you can "externalize" points 3 and 4 via Test Fragment
Related
During the jmeter run,a log file is created and stored in a location with timestamp. i want to refer the same filename in the next postprocessor. how do we achieve it
You want to get the name of the .jtl results file in JMeter script?
Something like:
?
If yes, you can use a suitable JSR223 Test Element and the following Groovy code:
import org.apache.jmeter.reporters.ResultCollector
import org.apache.jorphan.collections.SearchByClass
def engine = engine = ctx.getEngine()
def test = engine.getClass().getDeclaredField('test')
test.setAccessible(true)
def testPlanTree = test.get(engine)
SearchByClass<ResultCollector> resultCollectorSearch = new SearchByClass<>(ResultCollector.class)
testPlanTree.traverse(resultCollectorSearch)
ResultCollector resultCollector = resultCollectorSearch.getSearchResults().first()
println('Current .jtl file name: ' + resultCollector.getFilename())
I am facing one problem during uploading multiple files on server. I implemented some logic and fetched files one by one from a folder . But in HTTP request my URL is something like {Container name} followed by {Filename}.
My problem is in filename parameter value what should i passed so that every files will be uploaded on server .
My code is as below:-
File folder = new File("c:\\Test1\\Test");
File[] files = folder.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isFile();
}
});
for (int i=0; i < files.length; i++) {
vars.put("file_" + i, files[i].getAbsolutePath());
}
In file path i am passing this ${filesToUpload} ,parameter name and mimetype
I don't think your way is correct (unless you want to build the full raw body), you should rather invoke HTTPSamplerBase.setHTTPFiles() function using the following example steps:
Add JSR223 PreProcessor as a child of the HTTP Request sampler to which you want to add files
Put the following code into "Script" area:
import org.apache.commons.io.FileUtils
import org.apache.commons.io.filefilter.TrueFileFilter
import org.apache.jmeter.protocol.http.util.HTTPFileArg
import java.nio.file.Files
def files = FileUtils.listFiles(new File("c:/Test1/Test"), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)
def arguments = []
files.eachWithIndex { file, index ->
arguments.add(new HTTPFileArg(file.getAbsolutePath(), "your_parameter_name", Files.probeContentType(file.toPath())))
}
sampler.setHTTPFiles(arguments as HTTPFileArg[])
That's it, the code will dynamically read the files from folder and add the files from it to the request, just make sure to amend your_parameter_name to the real respective value
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It
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
Can we pass the beanshell assertion variable (in a thread) to cookie manager user defined variable (outside the thread) in jmeter ?
This is the image of user defined cookies which are been used on my request
This is bean shell variable
I don't think it will work this way, you can use something like:
In "init" thread group:
import org.apache.jmeter.protocol.http.control.CookieManager;
CookieManager manager = ctx.getCurrentSampler().getProperty("HTTPSampler.cookie_manager").getObjectValue();
props.put("cookiecount",String.valueOf(manager.getCookieCount()));
for (int i=0;i<manager.getCookieCount();i++){
// code to convert Cookie information to JMeter Properties
props.put("cookie_name_" + i, manager.get(i).getName());
//…..
}
In "Action" thread group:
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Cookie;
import org.apache.jmeter.testelement.property.JMeterProperty;
CookieManager manager = ctx.getCurrentSampler().getProperty("HTTPSampler.cookie_manager").getObjectValue();
int count = Integer.parseInt(props.getProperty("cookiecount"));
for (int i=0;i<count;i++) {
Cookie cookie = new Cookie(props.getProperty("cookie_name"+i),props.getProperty("cookie_value"+i), props.getProperty("cookie_domain"+i),props.getProperty("cookie_path"+i), Boolean.parseBoolean(props.getProperty("cookie_secure"+i)), Long.parseLong(props.getProperty("cookie_expires"+i)));
manager.add(cookie);
}
JMeterProperty cookieprop = ctx.getCurrentSampler().getProperty("HTTPSampler.cookie_manager");
cookieprop.setObjectValue(manager);
ctx.getCurrentSampler().setProperty(myprop);
Instead of having global HTTP Cookie Manager it is better to use 2 (or 3) separate ones local to the Thread Groups.
Consider moving to JSR223 Assertion and Groovy language as Beanshell performance might be a big question mark in case of high loads. See Scripting JMeter Assertions in Groovy - A Tutorial article for more details.
I need to test a web service with header-item lines with reading values from csv.
<urn:Requisition_BudgetReqExportHeaderDetails_Item>
<!--Zero or more repetitions:-->
<urn:item>
<urn:CompanyCode>
<urn:UniqueName>?</urn:UniqueName>
</urn:CompanyCode>
<urn:ERPRequisitionID>?</urn:ERPRequisitionID>
<urn:HoldTillDate>?</urn:HoldTillDate>
<urn:IsServiceRequisition>?</urn:IsServiceRequisition>
<urn:Name>?</urn:Name>
</urn:item>
</urn:Requisition_BudgetReqExportHeaderDetails_Item>
I can read values from CSV file but this web service is complex and items might be 1 or more than 2.
How can I handle this web service request?
You can use JSR223 PreProcessor like:
Add JSR223 PreProcessor as a child of your request
Put the code to generate the XML payload into "Script" area, an example one would look like:
def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)
xml.records() {
car(name:'HSV Maloo', make:'Holden', year:2006) {
country('Australia')
record(type:'speed', 'Production Pickup Truck with speed of 271kph')
}
car(name:'Royale', make:'Bugatti', year:1931) {
country('France')
record(type:'price', 'Most Valuable Car at $15 million')
}
}
sampler.addNonEncodedArgument("", writer.toString(), "")
Amend it to match your requirement
When you run your test the JSR223 PreProcessor will generate the request body and set it in the HTTP Request sampler
References:
sampler - a shorthand to HTTPSamplerProxy class, see the JavaDoc for all available methods and fields
Groovy - Creating XML - learn how to create XML data using Groovy language
Groovy is the New Black - an introduction to Groovy scripting in JMeter