Creating dynamic Response Assertion in Jmeter - jmeter

I am trying to run tests on JMeter and I expect a certain format of text in response assertion but it can change dynamically depending on the request. The response that I am expecting is something similar to as shown below :
{
"method": "<<Getting from the csv config file",
"student_id": "<<getting from the csv config file>>",
"term_id": "<<Getting from the csv Config file>>",
"crns": [{
"status_cd": "<<A numeric code from the response>>",
"section": "<<N or Y from response>>",
"message": "<<String value from response>>",
"crn": "<<Getting from the csv config file>>"
}]
}
I am not sure how to setup my response assertion to get the above format

I believe it is better to use JSON Path Assertion for JSON data. It is available via JMeter Plugins project and can be installed in a couple of clicks using JMeter Plugins Manager
See JSON Path - Getting Started and Advanced Usage of the JSON Path Extractor in JMeter to learn how to use JSON Path language for working with JSON data in JMeter

Related

Is it possible to parameterize Post requests payload and then encode it to base64 in Jmeter

The background is that I want to make a REST to Google pub/sub. Where the data need to follow this format:
Link to documentation of Pub/Sub format
My current solution is that I uses an BeanShell PreProcessor script to encode the payload to base64 before I send the request to the endpoint. This solution works, but I would like to
parameterize the data in the payload, instead of having the whole payload inserted as test data in the csv-file.
BeanShell PreProcessor used to encode the message before it is being sent:
import org.apache.jmeter.protocol.http.util.Base64Encoder;
String csv_payload = vars.get("csv_payload");
String csv_payload_encoded = Base64Encoder.encode(csv_payload);
vars.put("csv_payload_encoded", csv_payload_encoded);
Payload populated from the csv-file in Post request:
{
"messages": [
{
"data":"${csv_payload_encoded}",
}
]
}
Example of payload data stored in the csv-file that is sent in the request:
{"identId":"123456","requestId":null,"payload":{"header":{"requestid":1,"timeStamp":1617873956,"version":"0.0.0.1","eventId":0001,"creatorId":0,"messageTTL":34560},"body":{"checkid":001,"checkData":{"diagnosticsData":{"troubleSource":0,"data":"[2020-01-01 16:00:53.707961][[lat[0]][long[0]][alt[0]][canbetrust[0]][mars[0]]][signal[5]][TEM2 wake up]"}}}}}
Example of the encoded payload that the request sends to google pub/sub:
{
"messages": [
{
"data":"eyJpZGVudElkIjoiMTIzNDU2IiwicmVxdWVzdElkIjpudWxsLCJwYXlsb2FkIjp7ImhlYWRlciI6eyJyZXF1ZXN0aWQiOjEsInRpbWVTdGFtcCI6MTYxNzg3Mzk1NiwidmVyc2lvbiI6IjAuMC4wLjEiLCJldmVudElkIjowMDAxLCJjcmVhdG9ySWQiOjAsIm1lc3NhZ2VUVEwiOjM0NTYwfSwiYm9keSI6eyJjaGVja2lkIjowMDEsImNoZWNrRGF0YSI6eyJkaWFnbm9zdGljc0RhdGEiOnsidHJvdWJsZVNvdXJjZSI6MCwiZGF0YSI6IlsyMDIwLTAxLTAxIDE2OjAwOjUzLjcwNzk2MV1bW2xhdFswXV1bbG9uZ1swXV1bYWx0WzBdXVtjYW5iZXRydXN0WzBdXVttYXJzWzBdXV1bc2lnbmFsWzVdXVtURU0yIHdha2UgdXBdIn19fX19",
}
]
}
If there are any feedback I would appreciate it or any other improvements suggestion
for how I would be able to proceed in order to parameterize and encode the payload to base64 eg:
Example of
Don't use Beanshell, since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting
There is __base64Encode() function available via Custom JMeter Functions plugin bundle installable using JMeter Plugins Manager
If you CSV file has references to other JMeter Functions or Variables you can resolve them by wrapping into __eval() function like:
to read the file:
${__FileToString(somefile.csv,,)}
to read the file and resolve any functions or variables in it:
${__eval( ${__FileToString(somefile.csv,,)})
to read the file, resolve any functions or variables and Base64-encode the result:
${__base64Encode(${__eval( ${__FileToString(somefile.csv,,)})},)}
Demo:

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 to update Json file before sending as a request in Jmeter

In my Project, API Contract is changing frequently (every two sprints). From me it is very hard to update the payload in each 'http request' of project test cases.
I am looking for a solution to maintain a separate json file with the request. Update the request json file based on the test cases using Jmeter and send to server.
Do we have any solution for this?
Or please suggest if we have any other approach to handle this case.
sample JSON: original JSON has more than 600 lines.
{
abc:"abc",
xys:"xyz",
"abcd":[{
abc:"abc",
xys:"xyz",
abc:"abc",
xys:"xyz"
PQR:[{
abc:"abc",
xys:"xyz",
abc:"abc",
xys:"xyz",
}]}]
}
I can think of only one option:
Add JSR223 PreProcessor, it will be executed before the request
JSON file can be read using JsonSlurper
At this stage you can amend it according to your needs using Groovy language
Once you done you can construct the JSON back using JsonBuilder and write the generated new JSON back to the file
More information: Apache Groovy - Parsing and producing JSON

How can I dynamically post Request body (xml) and validate the response (xml)?

Is there a way to send the XML request dynamically and validate the XML response?
My scenario is:
I will have a CSV dataset config and inside the csv file I will have two column, the first one is for the inputXMLFilePath and the second column is the expectedXMLResposneFilePath.
So I need to have a JSR233 PreProcessor under HTTP request sampler, read the input file path convert it to the post body, and also has another JSR233 sampler for load the expected response from the expectedXMLResponseFilePath and compare it with the previous XML response. I have a snippet for JSON which is working fine. but for XML how can I do it?
You can use __FileToString() function for both use cases:
To send the XML request body, like ${__FileToString(${inputXMLFilePath},,)} (where ${inputXMLFilePath} is the variable from the CSV Data Set Config)
To validate the response using Response Assertion configured like:
Field to Test: Text Response
Pattern Matching Rules: Equals
Patterns to test: ${__FileToString(${expectedXMLResponseFilePath},,)}
You can use JMeter Functions literally at the any place of your Test Plan so their flexibility is higher than for other test elements. Also JMeter Functions are being compiled into native Java code therefore their execution speed will be higher and footprint will be less comparing to Groovy scripting.
Check out Apache JMeter Functions - An Introduction article to learn more about JMeter Functions concept.

Using BeanShell Assertion for saving failed response

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

Resources