Better way to execute Javascript in Jmeter - jmeter

SetUp part of my Jmeter script contains steps to bypass login page of my Web Application before generating real load. As a result of these steps, server sets specific cookie that proves successful loginization.
To do that, my script should execute Javascript function injected in response by server. Since it's a one-time procedure, I do it using WebDriver and execute Javascript within browser instance.
But I definitely can't do the same as a part of load thread as WebDriver is not a good idea (at all) for performance testing.
However, I'm still wondering is it a way to calculate JS without creating a browser instance, because my JS script is nothing but arithmetic calculations (complex though). So,
Any ideas about how to execute JS without creating browser instance are very much appreciated. Since I can write BeanShell code, it shouldn't be a big issue (just share the lib name that can create "virtual" browser for calculations not related to DOM). Not sure that it'll be faster, but I'll try to.
If I'm right and browser usage is the only possible solution, then I'm looking for a way to share one single browser window between different threads (even with delay for those who waits for it). Tried to use JavascriptExecutor, but don't know how to convert WebDriver to JavascriptExecutor (beanshell is written using too old Java, and I'm not familiar with its syntax and functionality). Can't use WebDriver plugin too as it doesn't allow just to create window without get("pageUrl").
Thanks for any ideas in advance.

You can use JSR223 Sampler, choose javascript from "Language" dropdown and place your code in "Script" area
You can use single browser instance using WebDriver Sampler for all threads in a loop, something like:
var ctx = org.apache.jmeter.threads.JMeterContextService.getContext()
var vars = ctx.getVariables();
for (var i=0; i< THREADS_NUMBER; i++) {
WDS.browser.manage().deleteAllCookies()
WDS.browser.get('LOGIN_PAGE_URL')
var cookie = WDS.browser.manage().getCookieNamed("COOKIE_NAME").getValue();
vars.put("cookie" + i, cookie);
}
it will generate JMeter Variables like:
cookie1=foo
cookie2=bar
etc.
So you will be able to refer variable values using __threadNum() function where required like:
${__evalVar(cookie${__threadNum})}
See The WebDriver Sampler: Your Top 10 Questions Answered guide for more information on using the WebDriver Sampler.

Related

Suspeciously long pauses between Click and SendKeys actions in WDS in JMeter

I have an action which fills in a form with 2 fields and clicks submit button.
Issue: load time for this sampler grew up during several script runs from 2-3 sec initially (which was visually close to manual execution) to 14-16 sec with no visible reason (no changes in application or script).
Investigation: ~4-5sec pauses between click into a field and sendKeys actions for both 2 fields in script when manually fields are clickable with no visible delays after form appears.
Log:
WDS code:
Q: Is there any explanation of such strange behavior with ~5sec + ~5sec pauses in each field?
What should I do to fix this issue with too long and unexplainable pauses which provide unrelevant results?
Should I consider to switch to JSR223/groovy or it is not sampler type & code-related problem?
Your question doesn't tell the full story so I don't think it's possible to come up with the comprehensive answer so far only few generic recommendations:
Take a thread dump at the moment when JMeter is "waiting" and doing nothing, it will allow you to detect what's going on there
Monitor JVM parameters using JVisualVM or equivalent, it might be the case the JVM is doing garbage collections to free up heap memory space, in this case you will have to tune JMeter for maximum performance
You're "finding" the element twice, the second line is absolutely unnecessary so instead of
wait.until(pkg.ExpectedConditions.visibilityOfElementLocated(pkg.By.xpath("some xpath")))
var element = WDS.browser.findElement(pkg.By.xpath("the same xpath"))
you can do it only once like:
var element = wait.until(pkg.ExpectedConditions.visibilityOfElementLocated(pkg.By.xpath("some xpath")))
XPath is the most powerful but the least performing locator strategy, if it's possible - try to stick to element ID attributes, if it is not possible - go for CSS Selectors
Follow JMeter Best Practices like don't run your test in GUI mode, avoid storing response data, etc.

How to clear cache for a sampler in JMeter

I have a jmeter script where I need to open a page multiple times. Hence, I kept this action under loop controller. What I observed is the response time of loading page is decreasing for every iteration. This could be due to caching. Can anyone help me on how to clear cache for this sampler after every iteration (I am referring to loop controller iteration here not thread group one).
Your requirement doesn't really make a lot of sense as well-behaved JMeter test should represent a real user using a real browser and real browsers caching strategy assumes minimizing the amount of downloaded assets by obeying Cache-Control headers
If you're aware of this good practice and still want to discard the cache for each iteration:
Add JSR223 PreProcessor as a child of the HTTP Request sampler which cache you want to clear
Put the following code into "Script" area:
sampler.getCacheManager().clear()
You can use HTTP Cache Manager in JMeter and check this checkbox to Clear cache each iteration?. You can follow the page to learn more about this. This applies to all the requests in the current thread. I know this is not what you are looking for but JMeter has only this option as UI setting.
Another way can be to use Beanshell PreProcessor to intercept the request and clear the cache on the run.
import org.apache.jmeter.protocol.http.control.CacheManager;
CacheManager clearCache = ctx.getCurrentSampler().getProperty("HTTPSampler.cache_manager").getObjectValue();
clearCache.clear();

How do I record a script in JMeter which adds a record in a website?

Currently, I am recording a script in jmeter by which I am adding a record in a website , but a problem is that while recording a script I am able to add a record in a website, but once recording has been done and after that if I will run a script again then, a script is not adding a record in a website.
can you please help me with this?
In the absolute majority of cases you will not be able to replay the recorded script without performing correlation.
Modern web applications widely use dynamic parameters for session management or CSRF protection so once you record your test you get "hardcoded" values and they need to be dynamic.
Assuming all above my expectation is that your test doesn't add record due to failed login or something like that. Inspect requests and responses using View Results Tree listener - this will allow you to identify which exact step is failing.
The process of implementing the correlation looks as follows:
Identify the element which looks to be dynamic either manually inspecting request parameters and look for "suspicious" patterns or record your test one more time and compare the recorded scripts looking for the parameters which differ
Inspect previous response and extract the dynamic value using a suitable post-processor. For HTML response times the best option is CSS Selector Extractor. It will allow you to extract the dynamic parameter value and store in into a JMeter Variable
Replace hardcoded recorded value with the variable from the step 2
Repeat for all dynamic parameters
Don't forget to add HTTP Cookie Manager to your Test Plan.

JMeter post-processor extracting javascript after evaluation from response body

The response body from a POST contains the following javascript:
var now = new Date();
document.location.href="/wwtb/entry.cgi?id=148e2743ad01572d55265c96ae91dc6c&uid=qastudent&fromlogin=1&ts=" + now.getTime();
I need to extract the value of ts after it's evaluated so that I can pass it as a parameter in my next GET.
As per JMeter project main page:
JMeter is not a browser, it works at protocol level. As far as web-services and remote services are concerned, JMeter looks like a browser (or rather, multiple browsers); however JMeter does not perform all the actions supported by browsers. In particular, JMeter does not execute the Javascript found in HTML pages. Nor does it render the HTML pages as a browser does (it's possible to view the response as HTML etc., but the timings are not included in any samples, and only one sample in one thread is ever displayed at a time).
Therefore you will not be able to extract the value "after it's evaluated" because it will never get evaluated.
JMeter's equivalent of Date.getTime() function is __time() function so if you put the following construction anywhere in your Test Plan:
/wwtb/entry.cgi?id=148e2743ad01572d55265c96ae91dc6c&uid=qastudent&fromlogin=1&ts=${__time()}
The ${__time()} bit will become substituted with the current timestamp in the runtime:
Check out Apache JMeter Functions - An Introduction article to get familiarized with JMeter Functions concept.

jMeter - Beanshell bsh.shared hashmap data in init file?

I have a jMeter project I'm working on which has thrown up all sorts of problems. Mainly due to storing and scoping of variable data throughout the run.
I now have things pretty much working and I'm using a Beanshell shared hashmap to store data through the run. I don't need to worry about thread safety due to the way I'm doing it.
It works, but it re-initialises itself each time a thread group runs. Despite putting the initialisation step outside all thread groups.
So, as I understand it, the solution is to put all the startup data into an initialisation file which is only run once on startup. But I can't figure out how I'm supposed to do that? I've copied the code from the Beanshell Preprocessor I was using previously into a ".bshrc" file and updated the jMeter properties file with the location of my ".bshrc" file, but it doesn't seem to work. It doesn't actually seem to have done anything. When I run the test, no values are present and everything fails.
I've tried using:
beanshell.init.file=../bin/data.bshrc
and
beanshell.preprocessor.init=../bin/data.bshrc
I've tried to find some sort of idiots guide to setting up an init file, but I can't find anything helpful. This is the first time I've had to make much serious use of Beanshell and my Java knowledge is VERY limited at best!
At the moment, I'm getting round it by running my test once with the original Beanshell pre-processor enabled. This sets up the hashmaps and they stay resident in memory from there on. I stop this run, disable the pre-processor, and all subsequent runs work just fine.
Anyone?
I would suggest using setUp Thread Group which is being executed prior to any other Thread Groups and define your test data there with a Beanshell Sampler like
bsh.shared.myMap = new java.util.HashMap();
bsh.shared.myMap.put("foo","bar");
// any other operations
After that in your main Thread Group(s) you can access myMap values in any Beanshell-enabled test element (Sampler, Pre/Post Processor, Assertion) as
log.info("foo = " + bsh.shared.myMap.get("foo"));
2014/07/22 10:06:48 INFO - jmeter.util.BeanShellTestElement: foo = bar
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.
If you use Beanshell for "heavy" operations I would recommend considering switching to JSR223 Sampler and Groovy language as in that case you'll get performance comparable to native Java code.

Resources