I am designing a load test in JMeter.
With the current application that we have whenever a HTTP request is sent, the web server will very occasionally send back a page with a message. To get around this we just have to reload the page. This page could come up for literally any HTTP request.
Is there any way to design a test in JMeter where when a sampler fails, the sampler simply retries?
I'm not sure how I can get a Beanshell sampler to resend a HTTP request.
It is possible via additional Beanshell Assertion
You can re-run arbitrary sampler from the Beanshell Assertion as simple as
ctx.getCurrentSampler().sample(null);
Add a Beanshell Assertion after all other assertions. It matters as assertions are being executed upside-down.
Put the following code into Beanshell Assertion's "Script" area (just change "message" to what your server returns on error.
import org.apache.jmeter.samplers.SampleResult;
if (new String(ResponseData).equals("message")) {
SampleResult result = ctx.getCurrentSampler().sample(null);
if (result.getResponseDataAsString().equals("message")) {
Failure = true;
} else {
SampleResult.setSuccessful(true);
}
}
You'll have only one result recorded.
If assertion passes 1st time - it'll be successful
If assertion fails 1st time and passes 2nd time - it'll be successful
If assertion fails 2 times - it'll be recorded as failed.
For extended information on Beanshell scripting check out How to use BeanShell: JMeter's favorite built-in component guide.
Create such hierarchy:
Thread Group (1 user, 1 second ramp-up, forever)
-While Controller (empty condition = forever)
--Counter (start – 1, increment – 1, reference name – counter)
--HTTP request
---Timer (I prefer constant Timer, responseble for pause betwee retrying)
---BeanShell Post Processor
BeanShell Post Processor should contains(pseudo code):
if(Integer.parseInt(vars.get("counter")>5)
{
prev.setSuccessful(false);
prev.setStopTestNow(true);
}
if(successCondition)
{
prev.setStopTest(true);
}
There is no direct way to achieve it, but I think you can use While controller in conjuction with Regex extractor to resend the failed requests.
Logical flow could be,
1. HTTP request
2. Regex extractor post processor - check response contains failure extract value in msg variable, default is success
3. While controller - run till msg=failure, default value of msg is success
Example screenshot,
Let me know if this works.
Related
I have test plan with following request in sequence with 2 loops.
ApiHttp request
Mqtt request
I need to run 1st loop & verify API reaponse is true or false:
If it's true, run Mqtt request , else start the 2nd loop and same verify the API response, if it's true run Mqtt else stop.
In above scenarios, I put beanshell to read the API response:
vars.put("response", new String(data));
But don't know how to verify of its true or false & execute the Mqtt. Any help pls.
Add If Controller as the very first test element under the Thread Group and use the __groovy() function as the condition:
${__groovy(vars.getIteration() <= 2,)}
Put ApiHttp request as a child of the If Controller
Add another If Controller after the ApiHttp request and use the following __groovy() function as the condition:
${__groovy(ctx.getPreviousResult().getResponseDataAsString().contains('true'))}
Add Mqtt request as a child of the If Controller
Add Flow Control Action sampler after the Mqtt request and configure it like:
First switch from Beanshell to JSR223 Test elements and use Groovy.
Use If Controller and just put in it:
${response}
To stop the test based on iteration number, be aware that a Loop Controller exposes iteration as a variable based on name of variable, for example if your LoopController is named LC, then you can access iteration as:
vars["__jm__LC__idx"].toInteger()
And to stop a test from Groovy using JSR223 Assertion you can throw:
throw new org.apache.jorphan.util.JMeterStopTestException();
See:
https://jmeter.apache.org/api/org/apache/jorphan/util/JMeterStopTestException.html
I have to performance test an application which does a PDF to PNG image conversion. For that, I have 3 requests to be sent, ie, 1 POST and 2 GET requests. My requirement is to measure the performance of one the GET request which does the conversion part and downloads the converted PNG file. Note that this GET request that download the image is dependent on the other POST and the GET request which checks the status of the job. The full work flow in a nutshell is as follows:
Send a POST request to trigger a job to generate a unique identifier string.
Using the string value generated in step 1 above, the GET request checks the status of creation of a PDF document. Since this process has dependencies, the GET request polls until a status of 'Complete' is returned in its response. If the response status is not 'Complete', then we have to retry this GET request.
And finally, once the response from step 2 is returned as 'Complete', the GET request to convert the generated PDF to PNG image has to be triggered.
So 3 requests above are dependent to each other and has to run sequentially as the input for one is the output of the previous request. So we have to run this in the same order (1__> 2 --> 3) for the entire duration of the performance test.
I have tried using the While controller, however, the issue I am facing is, the sampler inside the While controller (ie GET request in step 2 which checks the status) is getting executed only for a limited number of times and not for the entire test duration.
The jmx file I have created is as follows:
Test Plan{
Thread Group{
POST Request sampler{ //step 1
//stores unique string response to variable
}
User Defined variable (initialize a Status variable to null string, initialize a counter variable)
While Controller(condition '${__javaScript("${Status}" == "" && (${counter} < 4),)}')
{
GET Request Sampler { //step 2
Regular expression extractor to get the status from response and store to variable
}
JSR223 Post processor { //to check if the status value = 'Complete', otherwise set status back to null string
/*
String status = vars.get("labelStatus")
if(status.equals("Complete")){
log.info("Label Status is Complete");
}
else{
vars.put("labelStatus","")
}
*/
}//end of JSR223 post processor
}//end of while loop
GET Request sampler to download the PNG image //step 3
} // end of Thread Group
}//end of Test Plan
screenshot of my Jmeter script:
Ideally for each POST request I make (step 1), there should be a corresponding GET request (step 2) which checks for a particular status in response. If the response contains the matching text, then have to exit the while loop and continue with the next sampler (ie GET request in step 3 above) in the thread group. This needs to be repeated in each iteration.
As per your While Controller condition its children will be executed while ${Status} variable is empty or 4 times, whatever comes the first.
I fail to see where do you update the value of the ${Status} variable, it might be the case you made a typo and need to change it to ${labelStatus}?
I would recommend using Debug Sampler and View Results Tree listener combination in order to check the values of ${labelStatus} and ${counter} variables for each While Controller's iteration
Also pay attention to JMeter Scoping Rules as your last JSR223 PostProcessor is being executed after every sampler in the Thread Group and this is something you might want to change.
please could you give me an example on how to use a while loop to keep checking (polling) if my HTTP GET request (REST api call) has returned the successful response or not. Say for example, third attempt brings the successful response and I come out of the loop, How do I measure the time it has taken?
Please use While controller:
1) init counter JSR223 Sampler --> vars.put("counter","1");
2) while controller
3) inside while controller put your HTTP get
4) put a regex to retrieve what you are looking for (or JSON extractor)
5) Another JSR223 Assertion to check the result of what you retreived
if(!detail.equals("REGEX_FAILED")){
......
}
7) timer so you wait
8) increment counter
I want to save the request and response of the sample into a text file, if response assertion is failed.
Here I can save the request and response it to a text file. But I am struck where,
how to check the whether response assertion is passed or failed for the respective sample.
How to validate the is current "Http Request" sample is passed or failed?
Thanks In advance.
Add Beanshell Listener as a child of your HTTP Request sampler which has Assertion(s)
Put the following code into "Script" area:
import org.apache.jmeter.assertions.AssertionResult;
for (AssertionResult assertionResult : sampleResult.getAssertionResults()) {
if (assertionResult.isFailure()) {
//do what you need here
}
}
As Listeners are executed after assertions the listener will have information regarding all assertion results therefore you will be able to conditionally store request/response details into a file.
Be aware that starting from JMeter version 3.0 the Groovy scripting engine is being shipped with JMeter so consider switching to JSR223 Listener and replacing all your Beanshell Test Elements with the JSR223 equivalents, performancewise it would be much better.
Let's say I have a Jmeter test which emulate some user login and several more actions. I also have 'start new thread on error' turned on. So in case some user fail - it will just get another user and keep processing the test for specified amount of time.
But I have some periodic calls for authorized user and to emulate them I'll need to use "Inter-Thread Communication" and additional thread group(-s). Basically this works fine in following way - in main thread I do login and fill some FIFO queue with required cookies, and obtain that cookie in another thread group. In that another thread group I do also check one more FIFO queue (that is filled on user logout), and stop that thread if get what I need.
The problem here is when main thread is fail after login. In that case child thread will be executed 'forever', since that periodic call keeps session active.
And the question - is there some possibility in Jmeter to execute some action on thread failure (smth like finally block). Basically I need fill that second FIFO queue either on logout or on thread failure
Add a Beanshell Assertion at the same level as all your requests go. It'll apply to each of the requests and in case of failure you'll be able to do what your need.
Something like:
Thread Group
Login Sampler
Some other Sampler
Some else Sampler
Beanshell Assertion
The example assertion code:
if (!SampleResult.isSuccessful()){
log.info("Test " + SampleResult.getSampleLabel() + " has failed");
// handle the error
}
See How to Use JMeter Assertions in 3 Easy Steps guide for more information on JMeter Assertions.
I also had to logout on sample error which needs something like try-catch-finally. An IF Controller with condition ${JMeterThread.last_sample_ok} and checked Evaluate for all children? as below, satisfied my need in a clean way:
TestPlan
HTTP Cookie Manager
HTTP Request Defaults
ThreadGroup - (continue on error)
HTTP Request - login
IfController - (Evaluate ${JMeterThread.last_sample_ok} for all children)
HTTP Request 1
HTTP Request 2
....
HTTP Request n
HTTP Request - logout (after and outside of IF)