I have the following scenario to emulate in jMeter:
10 users (ThreadGroup) are logging in and each user (ThreadGroup) should wait/delay for 10 secs to start next user (ThreadGroup). How do I implement this?
Right now I have something like this:
ThreadGroup(10usrs)
Http Sampler Request(LogIn)
Http Sampler Request(LookUpStatement)
Http Sampler Request(ControlPanel)
Http Sampler Request(CapAvailableList)
Http Sampler Request(LoadAllChatCount)
Http Sampler Request(ReturnNotificationCount)
Timer (10 sec)?
Which timer should i use? Constant Throughput Timer or Stepping Throughput Timer
Is it even possible or do I have to use some workaround?
Any help with tutorial or links much appreciated.
You can start a new user (up to 10 users) each second by using the "Stepping Thread Group"
http://jmeter-plugins.org/wiki/SteppingThreadGroup/
If you only need to create a timer between each requests, putting a Constant Timer will do the trick. (although I would prefer the Gaussian Random Timer)
The Constant Throughput Timer will create a dynamic delay time to limit your Hits/s produced by your script - I don't think this is what you meant.
Best,
You can use the test action sampler along with beanshell timer for this. In the below steps, we use the pacing of 4500 milliseconds. Irrespective of how much time the previous request took, it will apply the remaining time. If the request took 1000 mSec, it will apply 4500-1000 = 3500 mSec as the pacing.
Add a Test Action Sampler
In the "Duration (milliseconds)" field, set the value as simply ${mydelay}
Right Click Test Action Sampler > Add > Timer > Beanshell timer. Paste the following code.
Long pacing = 4500 - prev.getTime();
if (pacing > 0) {
Integer iPacing = pacing != null ? pacing.intValue() : null;
log.info(String.valueOf(iPacing));
vars.put("mydelay", String.valueOf(iPacing));
return iPacing;
} else {
vars.put("mydelay", "0");
return 0;
}
Use a Test Action with JSR223 Timer in the beginning (JSR timer is the beginning is not really necessary since all its doing is setting the start time) and the end of the main loop for which you want to maintain the pace and use the code below to achieve the interval pacing. Action in Test Action should be set to Pause for the duration of 0ms.
Also create a JMeter variable called pacing which should hold the value of pacing you require.
Use the following code in the JSR223 Timer under the Test Action.
/**
* PACING START
* Set the start time for pacing calculation
*
*/
def d = new Date()
try {
vars.put("pacingStartTime", "${d.getTime()}")
return 1
}
catch (Exception e) {
log.warn("[ Pacing: Failed to set the start time ]", e)
throw e;
}
Use following in the timer at the end.
/**
* PACING END
* Calculate the pacing and apply // return!
*
*/
def d = new Date()
try {
def pacing = Long.parseLong(vars.get("pacing")) // get the required pacing value from jmeter variable.
String startTime = vars.get("pacingStartTime") // get the start time which was set in the beginning of the loop
def diff = d.getTime() - Long.parseLong(startTime) // current time minus start time
def sleep = pacing > diff ? pacing - diff : 0 // logic for sleep time
log.info("[ Pacing: ${pacing}ms, Remaining time: ${sleep}ms ]")
return sleep
}
catch (Exception e) {
return 1000
log.warn("[ Pacing: Failed to calculate pacing ]", e)
throw e;
}
Related
I'm using the jmeter api to develop pressure testing tools,
How to modify the parameters of jmeter at runtime? such as the number of thread pools,
ConstantThroughputTimer.throughput
demo
github,but not found answer
You cannot change the number of threads in the runtime (at least not with JMeter 5.5)
What you can do is to use Constant Throughput Timer in combination with Beanshell Server to control requests execution rate.
I tried and found the answer by writing my own code. Parameters can be dynamically modified in the form of apis. Just call JMeterUtils.getJMeterProperties().setProperty("throughput", prop)。
ConstantThroughputTimer :
ConstantThroughputTimer timer = new ConstantThroughputTimer();
long rpsCalc = (long) (rps * 60);
String paramStr = "${__P(throughput,50)}";
timer.setProperty("calcMode", 2);
StringProperty stringProperty = new StringProperty();
stringProperty.setName("throughput");
stringProperty.setValue(paramStr);
timer.setProperty(stringProperty);
timer.setEnabled(true);
timer.setProperty(TestElement.TEST_CLASS, ConstantThroughputTimer.class.getName());
timer.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName());
return timer;
I am trying to calculate SSE traffic latency in a simple load test using the following JSR223 Sampler:
EventHandler eventHandler = eventText -> {
count++;
// get the time from the server
def result = eventText.substring(eventText.indexOf("data='") + 6, eventText.indexOf("', event")).trim() as Long;
def currenTime = System.currentTimeMillis();
def diff = currenTime - result;
list.add (diff);
resp = resp + "Time from server:" + result + ", JMeter time:" + currenTime + ", diff:"+ diff +"\n";
};
SSEClient sseClient = SSEClient.builder().url(pURL).eventHandler(eventHandler).build();
sseClient.start();
sleep(SLEEP_TIME);
sseClient.shutdown();
The time from the server (NodeJS -JavaScript) is Date.now() and the time on JMeter is System.currentTimeMillis()
Both Server and JMeter are on the same computer.
It seems that the time methods are not aligned as I can see that in some cases the JMeter time is earlier than the server time:
So I cannot trust the results...
Any other methods I should use on the JavaScript side or the JMeter side?
You cannot trust the results in any case because having the system under test and the load generator on the same machine is not the best idea, you won't get reliable results due to race conditions. Moreover it will be much harder to analyze the bottlenecks even with PerfMon Plugin
Also as per System.currentTimeMillis() function JavaDoc:
Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
So if you want to measure the time difference between previous and next SSE you can consider using System.nanoTime()
However it's better to move JMeter to another machine and preferably a Linux as the precision of System.currentTimeMillis() function there is much higher
I am using JMeter Webdriver sampler for the application UI response time measurement. I am facing issue with the wait function. For example the login page loads between 10 to 120 secs. So I have the following code for the login page in Webdriver sampler for the page load check.
var ui=JavaImporter(org.openqa.selenium.support.ui)
var wait=new support_ui.WebDriverWait(WDS.browser,120)
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(pkg.By.className('logout-btn-hover')))
The issue is even after the page load completely, JMeter is still waiting to perform the next action. This waiting time will reduce if I reduce the 120 secs.But sometimes the application will take 120 secs to load also so I need to keep 120 secs.
I am writing the time to a log file once the sampler completes its action. Because of the wait time issue I am not able to calculate time properly.
There are at least 2 errors in your script, it should look something like:
var ui=JavaImporter(org.openqa.selenium.support.ui)
var wait=new ui.WebDriverWait(WDS.browser,120)
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(org.openqa.selenium.By.className('logout-btn-hover')))
Check out jmeter.log file for any suspicious entries, in particular for something like:
ERROR c.g.j.p.w.s.WebDriverSampler: Expected condition failed: waiting for visibility of element located by By.className: logout-btn-hover (tried for 120 second(s) with 500 milliseconds interval)
Double check your CSS selector
Consider refactoring your code to look for the logout button(?) in a loop with verbose logging for each step. Sample code:
var pkg = JavaImporter(org.openqa.selenium)
WDS.sampleResult.sampleStart()
WDS.browser.get('http://example.com')
var start = new Date().getTime()
var attempt = 1
while (new Date().getTime() - start < 5000) {
try {
var logout = WDS.browser.findElement(pkg.By.className('logout-btn-hover'))
WDS.log.info('Element found')
break
}
catch (err) {
WDS.log.info('Attempt # ' + attempt + ', Element not found')
java.lang.Thread.sleep(1000)
attempt++
}
}
WDS.sampleResult.sampleEnd()
Example output when the element is not found:
Example output when the element is found:
Check out The WebDriver Sampler: Your Top 10 Questions Answered article for more information on using WebDriver sampler in JMeter scripts.
How can I get an overall PASS/FAIL result for a JMeter thread group without using a post processor on every sampler?
I've tried using a beanshell listener, but it doesn't work for instances where there are multiple samplers inside a transaction controller with "Generate Parent Sample" enabled. In that case, the listener only gets called once per transaction controller and I'm only able to access the result of the last sampler inside the transaction controller.
Edit:
I would like to be able to save a pass/fail value as Jmeter variable or property for the thread group. If one or more components of the thread group fail or return an error, then that would be an overall fail. This variable will then be used for reporting purposes.
My current beanshell listener code:
SampleResult sr = ctx.getPreviousResult();
log.info(Boolean.toString(sr.isSuccessful()));
if (!sr.isSuccessful()){
props.put("testPlanResult", "FAIL");
testPlanResultComment = props.get("testPlanResultComment");
if(testPlanResultComment == ""){
testPlanResultComment = sr.getSampleLabel();
}else {
testPlanResultComment = testPlanResultComment + ", " + sr.getSampleLabel();
}
props.put("testPlanResultComment", testPlanResultComment);
log.info(testPlanResultComment);
}
If you call prev.getParent() you will be able to fetch individual sub-samples via getSubResults() function, something like:
prev.getParent().getSubResults().each {result ->
log.info('Sampler: ' + result.getSampleLabel() + ' Elapsed time: ' + result.getTime() )
}
log.info('Total: ' + prev.getParent().getTime())
Demo:
More information: Apache Groovy - Why and How You Should Use It
I am running a database download in a background thread. The threads work fine and I execute group wait before continuing.
The problem I have is that I need to start an activity indicator and it seems that due to the group_wait it gets blocked.
Is there a way to run such heavy process, ensure that all threads get completed while allowing the activity indicator to run?
I start the activity indicator with (I also tried starting the indicator w/o the dispatch_async):
dispatch_async(dispatch_get_main_queue(), {
activityIndicator.startAnimating()
})
After which, I start the thread group:
let group: dispatch_group_t = dispatch_group_create()
let queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //also tried QOS_CLASS_BACKGROUND
while iter > 0 {
iter--
dispatch_group_enter(group)
dispatch_group_async(group, queue, {
do {
print("in queue \(iter)")
temp += try query.findObjects()
query.skip += query.limit
} catch let error as NSError {
print("Fetch failed: \(error.localizedDescription)")
}
dispatch_group_leave(group)
})
}
// Wait for all threads to finish and proceed
As I am using Parse, I have modified the code as follows (psuedo code for simplicity):
trigger the activity indicator with startAnimating()
call the function that hits Parse
set an observer in the Parse class on an int to trigger an action when the value reaches 0
get count of new objects in Parse
calculate how many loop iterations I need to pull all the data (using max objects per query = 1000 which is Parse max)
while iterations > 0 {
create a Parse query object
set the query skip value
use query.findObjectsInBackroundWithBlock ({
pull objects and add to a temp array
observer--
)}
iterations--
}
When the observer hits 0, trigger a delegate to return to the caller
Works like a charm.