Using Jmeter 2.12, what could cause the cookies to fail to reset during a JMeter Loop Controller? I've tried everything I can think of, but each time through the loop, one of the cookies from a previous login still remains. It doesn't seem to actually clear the cookies.
Here is how I put together my loop:
Thread Group 1
-- Loop Controller (3x)
-- Simple Controller
-- HTTP Header Manager
-- HTTP Cookie Manger (with 'Clear cookies each iteration?' enabled)
-- BeanShell sampler - with code that tries to clear all cookies
-- HTTP /login (gets cookies and auth headers)
-- ... various HTTP Samplers ...
-- HTTP /logout
I tried adding a Beanshell sampler with this code (as shown above) but it doesn't seem to do anything:
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.HeaderManager;
CookieManager cManager = sampler.getCookieManager();
cManager.clear();
HeaderManager hManager = sampler.getHeaderManager();
hManager.clear();
Ok, I figured out the problem. Even though the 'HTTP Cookie Manager' has an option called 'Clear cookies each iteration', the 'iteration' it speaks of does not include a Loop Controller. What it refers to is the 'Thread Group' iterations/loops only. This was not clear and I wasted half a day until I figured this out. Wouldn't have been confusing if the checkbox said 'Clear cookies each Thread Group iteration' instead. Very disappointing.
Loop Controller doesn't increment iteration. You can test it by evaluating vars.getIteration() Beanshell code line. Iteration is being incremented on Thread Group level. To override this you can call vars.incIteration() method in any Beanshell-enabled Test Element (Sampler, Pre/Post Processor, Assertion, etc.)
You Beanshell code for clearing cookies actually does nothing as cManager instance isn't being passed back to the sampler. You need to modify your code as follows:
CookieManager cManager = sampler.getCookieManager();
cManager.clear();
sampler.setCookieManager(cManager);
So sampler could have that "cManager" instance with cleared cookies
See How to use BeanShell: JMeter's favorite built-in component guide for more information on Beanshell scripting in Apache JMeter.
Related
I know that I can stop a thread conditionally in JMeter.
In my script I'm sending a requests and then I'm extracting their response json to further process it. There are some rare cases, where the parameter response provides some value that I cannot process in further steps.
I could actually detect this valid response by extracting another parameter. Would it be possible to just restart the thread based on condition, instead of stopping it?
Without scripting, you can add Flow Control Action (was: Test Action )
Choose Target: Current Thread and Action: Start Next Thread Loop
It'll skip "damaged" thread and continue to the next thread
For further researchers:
The easy way to start another iteration of a thread based on condition (i.e extracting some data out of json) is to use a BeanShell Sampler in way like described above.
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterContext.TestLogicalAction;
String statVar = vars.get("statusVariable"); //getting some data for condition check (statusVariable is a variable that has been set previously in the Jmeter JSON Extractor)
if(statVar.equals("NOK")){ . //checking the condition
SampleResult.setTestLogicalAction(TestLogicalAction.START_NEXT_ITERATION_OF_THRE
AD); //Starting thread again (it starts the thread from the beginning, so we may compare this to restart effect)
}
We have a service that works the following way:
First, a request with search parameters is sent, for which we get back a searchId. This searchId is then used to continue fetching information until service response it has no more data left (hasMore parameter becomes "false").
The question is this - I have set up jMeter to send first requests, but not certain how then to keep sending requests in parallel for each response in the Thread Group, and need your advice on it. My thought was to set up another Thread Group since I cannot set it inside the first one, but then how do I get access to responses and process them in parallel?
EDITED:
This is what I ended up with. First Beanshell Sampler extracts searchId and hasMore and puts it into vars. Second Sampler extracts hasMore and again puts it into vars, overwriting the first. At the end, the While loop worked as intended, using ${__javaScript("${hasMore}" == "1",)}.
I would recommend designing your test as follows:
Request to get searchId
While Controller with condition like ${__javaScript("${hasMore}" != "false",)}
Request to continue to fetch information
PostProcessor to extract hasMore parameter and store it into the relevant JMeter Variable
This way "fetch information" requests will be executing until hasMore parameter becomes false. See Using the While Controller in JMeter article for more details.
I suggest 2 Thread group
First Thread group:
Save searchIds in file (JSR223 Sampler) or database (JDBC Sampler) with key as counter (1,2,...) and value as the searchId value
Save a number of IDs in property ${__setProperty(threadCount,${counter})}.
Second Thread group:
In definition - Number of thread use ${__P(threadCount)}
Read from file (JSR223 Sampler) or database (JDBC Sampler)
using ${__threadNum} as key get the relevant searchId you need
As you can see on the herewith image, I'm trying to debug Http requests. So in order to do that I've attached an Listener and a debug post-processor.
The problem is that while my http request's response code is 401, debug post-processor shows me an 200!!
Moreover, in a If Controller I've written this condition: ${JMeterThread.last_sample_ok} == false, and the code under it, is never reached!
Any ideas?
On the Sampler Result tab you see the result related to Debug PostProcessor itself. I.e. in this case it tells you that Debug PostProcessor finished successfully with the Response code=200 and Size in bytes = 1516
Then on Request tab it will show you the configuration of the Debug PostProcessor.
Now if you look at the Response Data tab, this is where you see what Debug PostProcessor actually returned. The thing is it has no ability to show the result of the parent sampler, only its configuration. So as a poster mentioned above, you cannot use it to look at result of the parent sampler. And frankly you don't need to, since you can see the result of any sampler by clicking on it in the View Results Tree, and selecting Sampler Result / Response Data.
The Debug Sampler (and the Debug Post-Processor) doesn't do what I think you think it does.
It isn't debugging in the sense that you might be used to: it won't let you set a breakpoint and step by step through it. Instead, it gives you a list of all of the variables and their values in the "Response Data" tab. This lets you make sure that the variables that you're using are what you think they are.
Because that request- the Debug Request- succeeded, that's what's giving you the 200 response.
A 401 response makes it seem like your Access Tokens aren't being set correctly. I'd check the Debug Sampler and compare the Variables in there to what you're expecting.
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.
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)