Using BeanShell Assertion for saving failed response - debugging

I'm trying to save the response of failed requests into log but unsuccessfully.
I have HTTP requests which each one has its own Response assertion, and once in a while through my load test a response doesn't meet the requirements of the Response Assertion, so I want to fail it.
I tried to add this code to the BeanShell Assertion following this post:
if (Boolean.valueOf(vars.get("DEBUG"))) {
for (a: SampleResult.getAssertionResults()) {
if (a.isError() || a.isFailure()) {
log.error(Thread.currentThread().getName()+": "+SampleLabel+": Assertion failed for response: " + new String((byte[]) ResponseData));
}
}
}
The Test plan itself looks like this:
In user defined variables I've added the following:
Name: DEBUG
Value: (none)
I ran this program through the non GUI mode - cmd and on purpose made a response fail (response assertion failed it) but I did not get any error response logged to my log file.
What am I doing wrong?
thanks

First of all if your goal is to just save failed responses, together with assertion results, you don't need any custom code. You can add Simple Data Writer configured like this:
Option 2: If you want to write responses into the log file, then you need custom script. But in that case I'd suggest using BeanShell Listener (unlike assertions and other objects, there's only 1 instance of listener for all threads, so it's more economical, and less chance to create a bottleneck at log writing).
Also according to your script, the value of DEBUG must be true, but as you mentioned, you did not set it to true (empty string will be resolved to false by Java's valueOf). So change it to
Name: DEBUG
Value: true
Here's how such BeanShell Listener's script looks:
if (Boolean.valueOf(vars.get("DEBUG"))) {
for (a: sampleResult.getAssertionResults()) {
if (a.isError() || a.isFailure()) {
log.error(sampleResult.getThreadName() + ": "
+ sampleResult.getSampleLabel() + ": Assertion failed for response: "
+ sampleResult.getResponseDataAsString());
}
}
}
Option 3 is to stay with your original solution, then you need to fix the variable assignment (as I mentioned before).

I would rather let JMeter do this automatically, it is the matter of a couple of properties, to wit:
First of all, you need to tell JMeter to store its results in XML format:
jmeter.save.saveservice.output_format=xml
Second, you can amend the following property values to configure JMeter to store assertion failure message and data into .jtl results file
jmeter.save.saveservice.assertion_results_failure_message=true
jmeter.save.saveservice.assertion_results=all
Probably the most useful option: simply save response data for failed samplers:
jmeter.save.saveservice.response_data.on_error=true
The above properties can be either put into user.properties file (located in JMeter's "bin" folder, JMeter restart is required to pick the changes up) or you can pass them via -J command line argument like:
jmeter -Jjmeter.save.saveservice.output_format=xml -Jjmeter.save.saveservice.response_data.on_error=true ....
See Apache JMeter Properties Customization Guide for more information on working with JMeter Properties to tune various aspects of JMeter configuration

Related

Is there a way in JMeter to get the response message from the network tab?

I am trying to get the error message from the network tab in JMeter:
I have inserted the response assertion looking for a 200 or 201. However, when a test fails, it only tells me it is looking for one of the values, but not a message like in the response section of the network tab. For example, if it is a bad request, I see the 400, but no message like "uid cannot be empty, name cannot be empty". Is there a way to pull this information in JMeter?
With "normal" Response Assertion you cannot, if you want to apply some custom logic you need to perform some custom scripting.
For example if you want to add response body to the Assertion message you can play the following trick:
Add JSR223 Assertion after the Response Assertion
Put the following code into "Script" area:
prev.getAssertionResults().each { assertionResult ->
if (assertionResult.isFailure()) {
assertionResult.setFailureMessage(assertionResult.getFailureMessage() +
System.getProperty('line.separator') +
'Response data:' +
System.getProperty('line.separator') +
prev.getResponseDataAsString())
}
}
That's it, the above code will add the response data to any failing assertion, hopefully this is what you're looking for.
Going forward you might want to migrate all the assertion logic into the JSR223 Assertion and Groovy, see Scripting JMeter Assertions in Groovy - A Tutorial article for more details.

JMETER: Need to send all entries in a CSV file to HTTP request body in 'one' request

I'm trying to solve a test data issue in Jmeter. Can anyone of you have a look at below problem statement and advise here please ?
Requirement: Need to send all entries in a CSV file to HTTP request body in 'one' request to the end point.
Example CSV File:
"adsfas123wsf00000wqefqwe52145t10000",
"fdfrgvergq120947r0000dwsfqwaef237sadf",
"wfrqwef7865034r78tkahsefjh6985r7asfdaf",
"qefqwe52145t10000adsfas123wsf00000w",
"wsfqwaef237sadffdfrgvergq120947r0000d"
HTTP Request Body:
["${data}"}]
When the data is substituted, I should be able to get below output.
[
"adsfas123wsf00000wqefqwe52145t10000",
"fdfrgvergq120947r0000dwsfqwaef237sadf",
"wfrqwef7865034r78tkahsefjh6985r7asfdaf",
"qefqwe52145t10000adsfas123wsf00000w",
"wsfqwaef237sadffdfrgvergq120947r0000d"
]
Problem Statement: When I use CSV data set config. file, I'm unable to concatenate all entries into one single request body. My understanding is, CSV data set config. the file is not the right option here.
Did some search in StackOverflow and followed a method to achieve above using JSR223 PreProcessor' and the link is, How to send multiple json body using jmeter?.
Followed the above link and tried added below custom code provided.
def builder = new StringBuilder()
new File('/path/to/plans.csv').readLines().each { line ->
builder.append(new File(line).text).append(System.getProperty('line.separator'))
}
sampler.getArguments().removeAllArguments()
sampler.addNonEncodedArgument('', builder.toString(), '')
sampler.setPostBodyRaw(true)
Upon running, I get below error message,
Caused by: java.io.FileNotFoundException,
"adsfas123wsf00000wqefqwe52145t10000",
"fdfrgvergq120947r0000dwsfqwaef237sadf",
"wfrqwef7865034r78tkahsefjh6985r7asfdaf",
"qefqwe52145t10000adsfas123wsf00000w",
"wsfqwaef237sadffdfrgvergq120947r0000d" (The filename, directory name, or volume label syntax is incorrect)
If the file is not found, then how come the entries are read and displayed in the log viewer?
Also, how do I link the output of custom code to the request body? Or is it taken care of by the custom code itself?
You have an error in your code, change this line:
builder.append(new File(line).text).append(System.getProperty('line.separator'))
to this one:
builder.append(line).append(System.getProperty('line.separator'))
If you want to send the full contents of the file you don't even need to go for scripting, you can use __FileToString() function right in the "Body data" tab of the HTTP Request sampler:
${__FileToString(/path/to/plans.csv,,)}
And last but not the least if you need to generate JSON from the plain text it might be a better idea to go for JsonBuilder class, see Apache Groovy - Why and How You Should Use It and Apache Groovy - Parsing and producing JSON
Two steps:
Add a User Parameter Pre-processor before the HTTP request:
Name: DATA
User_1: ${__FileToString(/path/to/plans.csv,,)}
Add the following to request body:
${DATA}

how can I run multiple if controller in jmeter

I am currently working in a heavy load test, I have one login request which access with user and password and basic auth, I have to validate some info from the response and I am using assertions but I need to apply different kind of assert depending on the code response and to be able to do that I am using an if control putting the assertions inside as a child, the problem begins when I try to execute the assertions with an error code response, some how the if controller is not taking the value of the variable I created to store the code response. could some one help me? thanks!
You cannot put assertion as a direct child of the If Controller. In fact you can, however it will not make any sense as assertions obey JMeter Scoping Rules and since there is no any Sampler in the Assertion scope - it will simply not get executed.
I would recommend going for JSR223 Assertion where you have all power of Groovy SDK and JMeter API in order to set up your custom pass/fail criteria. The pseudo code would be something like:
if (SampleResult.getResponseCode().equals('200')) {
//do what you need when response code is 200
//for example let's check if response contains "foo" line
if (!SampleResult.getResponseDataAsString().contains('foo')) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Failed to find "foo" line in the response')
}
}
else if (SampleResult.getResponseCode().equals('300')) {
//do what you need when response code is 300
}
else if (SampleResult.getResponseCode().equals('400')){
//do what you need when response code is 400
}
else {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Unexpected response code: ' + SampleResult.getResponseCode())
}
References:
SampleResult documentation
AssertionResult documentation
Scripting JMeter Assertions in Groovy - A Tutorial

Beanshell assertion script failing in Linux machine and working in windows

IN JMeter I want some of the 500 internal server errors to NOT be marked as failures if the response contains a specified text. All 500 server errors are marked as failures.written code to make it as pass for all fail cases.same code is working without error in windows, but getting all samplers are fails in linux machine.
if (ResponseCode.equals("412") == true)
{
SampleResult.setResponseOK();
}
else if (ResponseCode.equals("500") == true)
{
SampleResult.setResponseOK();
}
You need to add SampleResult.setSuccessful(true);, also remove == true which is redundant and remove duplicate code:
if (ResponseCode.equals("412") || ResponseCode.equals("500")) {
SampleResult.setResponseOK();
SampleResult.setSuccessful(true);
}
Also consider change ResponseCode to responseCode according to Java/Oracle parameter name conventions.
You can achieve this using Response Assertion, just check Ignore Status box. For example, below configuration mark affected sampler(s) as successful if response will contain foo
Check out Response Assertions in JMeter 3.2 - New and Improved article for more information on using Response Assertion to add pass/fail criteria logic to your JMeter tests.
If you need more complex assertion logic which cannot be achieved using single or multiple Response Assertion instance(s) consider switching to JSR223 Assertion as it is recommended to use Groovy for scripting since JMeter 3.1
With regards to your question itself, double check JMeter's "lib" folder of Linux machine contains bsh-2.0b5.jar file for Beanshell scripting and groovy-all-2.4.10.jar for Groovy scripting.

How to log an error when a JDBC request returns no data from DB in Jmeter?

I need to know how to log an error when a JDBC request returns no data from DB in Jmeter.
I have got:
JDBC request
Query:
SELECT names
FROM customers
Variable names:
namesCustomers
Then I have got a BeanShell postProcessor with script:
import org.apache.jmeter.util.JMeterUtils;
JMeterUtils.setProperty("namesCustomer", vars.get("namesCustomer_1"));
And finally a simple controller called "set variables" which calls an external file with the following code:
vars.put("namesCustomer",JMeterUtils.getProperty("namesCustomer"));
The problem is that in another SOAP request I am using the variable namesCustomer_1, and if no data is returned from DB this request fails. I need to log an error when the JDBC returns no data.
If I add to the post processor:
log.error("Error example");
I see the error logged in jmeter.log when this request is ran. I need something like:
if(JMeterUtils.setProperty("namesCustomer", vars.get("namesCustomer_1")).toString().length()==0){
log.error("DB returned no results")
}
Any Ideas on how to log an error when the JDBC request returns no data?
It can be done a little bit easier. If JMeter Variable is not set, it'll be null, not empty string.
So I would suggest amending your code as follows:
String namesCustomer = vars.get("namesCustomer_1");
if (namesCustomer == null) {
log.error("namesCustomer_1 variable is not set");
} else {
props.put("namesCustomer", namesCustomer);
}
props is a shorthand to access current set of JMeter Properties, there is no need to use JMeterUtils.setProperty() method.
See How to use BeanShell: JMeter's favorite built-in component guide for more details on Beanshell scripting in Apache JMeter and a kind of Beanshell cookbook.

Resources