Jmeter/Selenium "stale element reference exception error - selenium

I have 10 threads on Jmeter all going into the same website but each thread has different accounts. I keep getting the Stale Element Reference Exception error on 1-3 threads per each test. The weird thing is that the threads that fail are different each time I run a test, and they all have the exact same path/code (besides the login credentials). What can I do to fix it?
When the a thread fails, it says "This site can't be reached" "examplewebsite.com took too long to respond" in the UI
enter image description here

Looking at Stale element reference page:
The stale element reference error is a WebDriver error that occurs because the referenced web element is no longer attached to the DOM.
So it means that you're trying to interact with the element which no longer exists.
Given This site can't be reached error it might be the case your application is overloaded or has another problem preventing proper displaying/rendering controls
You could try taking a screenshot in case of failure and/or printing the page source to jmeter.log file, this way you will have more information regarding what's going on when the page cannot be opened or element cannot be found/interacted with.
Example code:
try
{
WDS.browser.get('examplewebsite.com')
wait.until(conditions.presenceOfElementLocated(pkg.By.linkText('some-link')))
}
catch (err)
{
WDS.log.error(err.message)
var screenshot = WDS.browser.getScreenshotAs(pkg.OutputType.FILE)
screenshot.renameTo(new java.io.File('screenshot.png'))
WDS.log.info('Page source:')
WDS.log.info(WDS.browser.getPageSource())
exception = err
}
finally
{
throw (exception)
}
More information: The WebDriver Sampler: Your Top 10 Questions Answered

Related

if webdriver doesn't find an element then why not failing and quit the browser?

webdriver script is need to be closed if an element not find, my script is looking for an element but it is not exist on the webpage.
But my script is not stops the execution and quit the browser.
Instead of stops running, continuously waiting form long time, it is a miracle.
Execution needs to stop and Browser needs to close this is what i am expecting.
Please use try catch block. catch the NoSuchElementException and in catch block use driver.quit() method.
I had similar problem before, in my case changing:
driver.find_elements_by_xpath("")
to
driver.find_element_by_xpath("")
when you use "elements" it can return empty object however if you use "element" and the object is not found it will raise NoSuchElementException

Is there a change in the handling of unhandled alert in ChromeDriver and Chrome with Selenium?

I have a test that has been running fine for months. One thing it does is cause an alert and then verify the alert text. This is running with Selenium, Java and Chrome Driver 76.0.3809.68.
Lately it has been giving me the error:
"No such alert".
What happens is it clicks a button and waits for an alert if there:
try {
button.click();
} catch (UnhandledAlertException ex) {
// nothing
}
// then here goes code to accept the alert and get the text
when stepping through I see the alert. When I run it, I see the alert but it disappears. I did read something in the (Chrome Driver) release notes about unexpected alerts but it was a bit vague.
We have a global page which sets the options for Chrome, but everyone uses it and I don't want to screw up for other people. I did do it locally (did not git push) and it worked when I set the options before creating the driver.
Then I tried to do this, which does not seem to work. Should it, or once the web page is retrieved, can you not change options?
// Somewhere after web page retrieved this gets called:
public void setIgnoreAlert() {
ChromeDriver cd = (ChromeDriver) driver;
ChromeOptions cap = new ChromeOptions();
cap.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
Capabilities other = cap;
cd.getCapabilities().merge(other);
}
Which I was really hoping would work, but did not. Do you have to set the behavior before the Chrome instance comes up? That is, can you not set it as I did above? Any other suggestions on how to set it after the Chrome instance is up?
--- added later to answer question
This is done immediately after the try-catch block with button.click():
The method configPage.getAndHandleAlertPopUp() does the following:
public String getAndHandleAlertPopUp() {
Alert alert = driver.switchTo().alert();
String alertPopup = alert.getText();
alert.accept();
return alertPopup;
}
You saw it right. As per the User Prompts section within WebDriver - W3C Recommendation:
The common denominator for user prompts is that they are modal windows requiring users to interact with them before the event loop is unpaused and control is returned to the current top-level browsing context.
By default user prompts are not handled automatically unless a user prompt handler has been defined. When a user prompt appears, it is the task of the subsequent command to handle it. If the subsequent requested command is not one listed in this chapter, an unexpected alert open error will be returned.
User prompts that are spawned from beforeunload event handlers, are dismissed implicitly upon navigation or close window, regardless of the defined user prompt handler.
A user prompt has an associated user prompt message that is the string message shown to the user, or null if the message length is 0.
As per the discussion in ChromeDriver should return user prompt (or alert) text in unhandled alert error response:
When a user prompt handler is triggered, the W3C Specification states that the error response should return an "annotated unexpected alert open error" which includes an optional dictionary containing the text of the user prompt. ChromeDriver should supply the optional information.
Clearly, ChromeDriver was not compliant with this standard as the #Test were annotated with #NotYetImplemented as follows:
#Test
#NotYetImplemented(CHROME)
#NotYetImplemented(CHROMIUMEDGE)
#Ignore(value = HTMLUNIT, reason = "https://github.com/SeleniumHQ/htmlunit-driver/issues/57")
#NotYetImplemented(value = MARIONETTE,
reason = "https://bugzilla.mozilla.org/show_bug.cgi?id=1279211")
#NotYetImplemented(EDGE)
public void testIncludesAlertTextInUnhandledAlertException() {
driver.get(alertPage("cheese"));
driver.findElement(By.id("alert")).click();
wait.until(alertIsPresent());
assertThatExceptionOfType(UnhandledAlertException.class)
.isThrownBy(driver::getTitle)
.withMessageContaining("cheese")
.satisfies(ex -> assertThat(ex.getAlertText()).isEqualTo("cheese"));
}
Now this feature have been implemented with ChromeDriver v76.0:
Resolved issue 2869: ChromeDriver should return user prompt (or alert) text in unhandled alert error response [Pri-2]
So you have to handle the alert as a mandatory measure.
A bit more of your code code block for ...then here goes code to accept the alert and get the text... would have helped us to debug the issue in a better way. However here are the options:
Induce WebDriverWait for alertIsPresent() as follows:
new WebDriverWait(driver, 10).until(ExpectedConditions.alertIsPresent());
Your code trials was perfect perhaps as you have passed the CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE in a structured way:
public void setIgnoreAlert() {
ChromeOptions opt = new ChromeOptions();
opt.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
}
Another perspective would be to disable the beforeunload event handlers and you can find a couple of related discussions in:
How to disable a “Reload site? Changes you made may not be saved” popup for (python) selenium tests in chrome?
How to handle below Internet Explorer popup “Are you sure you want to leave this page?” through Selenium
Note: Once the WebDriver and Web Browser instances are initialized you won't be able to change the configuration on the run. Even if you are able to extract the Session ID, Cookies and other capabilities and session attributes from the Browsing Session still you won't be able to alter those attributes of the WebDriver.
You can find a detailed discussion in How can I reconnect to the browser opened by webdriver with selenium?

Wait until element is clickable does not timeout correctly

I'm having some problem handling timeouts as it doesn't seem to be working in every situation. I have defined the timeout as follows:
wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(60))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(NoSuchElementException.class);
Now, when I want to wait until an element is present on the page, I use this piece of code :
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
It works in most of the situation (wait for the element and timeout after 60 seconds) but lately we've been having trouble with some of the pages that get stuck loading (there's a message waiting for ... at the bottom left of the page). When this happens, I realize that this piece of code doesn't work properly. It doesn't timeout after 60 seconds but after 10 minutes.
Edit: Actually, trying to investigate my problem a little more, I realized it really comes from another line of code that also contains the wait:
wait.until(ExpectedConditions.elementToBeClickable(locator));
Basically, I click on a link that redirects to another page, wait for a button to be present, wait for the button to be clickable, and click on the button. So it detects the button is present but then it waits for it to be clickable and doesn't time out after 60 seconds.
So when I define my driver, I added the following line:
driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
In the console, I see the following line:
Timed out receiving message from renderer: 60.000
But how do I catch this exception? I tried to surround my wait with a try/catch but it doesn't work.
try {
wait.until(ExpectedConditions.elementToBeClickable(locator));
} catch (Exception e) {
logger.info("TEST");
throw new TimeoutException("element " + locator.toString() + " not found on the page");
}
How can I do it? Thanks.
You need to take care of a couple of things as follows:
Waiting until an element is present on the page ideally won't help much if your usecase is either to get any of the attributes, e.g. classname, innerHTML, etc of an element or to invoke click() on an element.
Instead depending on your usecase you need to use either visibilityOfElementLocated() or elementToBeClickable().
You can find a couple of detailed discussion in:
WebDriverWait not working as expected
Java Wrapper method for waiting for element to be available for Apache Cordova Webview driven App
Selenium: Check for the presence of element
The reason for the line of code wait.until(ExpectedConditions.presenceOfElementLocated(locator)) doesn't times out after 60 seconds but after 10 minutes may be due to the reason that, along with WebDriverWait you have also configured Implicit Wait and as per the documentation mixing up Implicit Wait and Explicit Wait can cause unpredictable wait times
To configure pageLoadTimeout you can use the following code block:
Code Block:
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(2, TimeUnit.SECONDS);
try{
driver.get("https://www.booking.com/hotel/in/the-taj-mahal-palace-tower.html?label=gen173nr-1FCAEoggJCAlhYSDNiBW5vcmVmaGyIAQGYATG4AQbIAQzYAQHoAQH4AQKSAgF5qAID;sid=338ad58d8e83c71e6aa78c67a2996616;dest_id=-2092174;dest_type=city;dist=0;group_adults=2;hip_dst=1;hpos=1;room1=A%2CA;sb_price_type=total;srfid=ccd41231d2f37b82d695970f081412152a59586aX1;srpvid=c71751e539ea01ce;type=total;ucfs=1&#hotelTmpl");
}catch(WebDriverException e){
System.out.println("WebDriverException occured");
}
driver.quit();
Console Output:
INFO: Detected dialect: W3C
[1563377008.449][SEVERE]: Timed out receiving message from renderer: 1.999
[1563377008.450][SEVERE]: Timed out receiving message from renderer: -0.001
[1563377008.461][SEVERE]: Timed out receiving message from renderer: -0.012
[1563377010.466][SEVERE]: Timed out receiving message from renderer: 1.998
[1563377010.467][SEVERE]: Timed out receiving message from renderer: -0.001
[1563377010.476][SEVERE]: Timed out receiving message from renderer: -0.010
WebDriverException occured
You can find a relevant detailed discussion in pageLoadTimeout in Selenium not working

Selenium - watch for an error condition AND run 'happy path' test code

My app displays an error dialog whenever a JavaScript error occurs. This is always a bad sign, so I want to set up my tests so that, if the error dialog appears, it causes the test to fail there and then.
So I'd like to do something like (very much pseudocode!);
// start a new 'guard' thread;
start {
found = this.driver.wait(untilVisible(By.css('.myErrorDialog')), VERY_LONG_TIMEOUT);
if (found) {
// the error dialog appeared! That's bad!
throw();
}
}
// now run the test
login();
clickButton();
testBannerContains();
But I'm having trouble and I think it has to do with the way Selenium schedules actions.
What I've found is that for a single driver, I can only schedule one thing at a time, so the guard I set up early in the test blocks the body of the test from starting.
Is there a better way to handle conditions like 'this should never happen', or a way to create two independent threads in the same test?
So the problem with the code you have is that it immediately runs it and waits for a VERY_LONG_TIMEOUT amount of time for that error dialog to appear. Since it never does, it continues to wait. You have already discovered that is not what you want... ;)
I haven't done anything like this but I think you want a JS event handler that watches for the event that is triggered when the error dialog appears. See the link below for some guidance there.
Can my WebDriver script catch a event from the webpage?
One option would be to watch for that event to fire and then store true (or whatever) in some JS variable. Before leaving a page, check to see if the variable is set to true and if so, fail the test. You can set and get JS variables using JavascriptExecutor. Some google searches should get you all you need to use it.

WinJS app with an uncatchable crash

I have random crashes in my WinJS application when navigating between pages.
The problem is that these crashes never occurs when the app is attached to the Visual Studio debugger; so I can't find where they come from.
I use the WinJS.Application.onerror event to prevent crashes, and log what happens, but as this works well when I try with a random exception, my "uncatchable" crashes doesn't seem to fire this event (I don't have anything logged).
Do you have any idea of what could cause these crashes, or any solution to find more informations ?
Sometimes errors can't fire the WinJS.Application.onerror for several reasons (in my app, the problem was in an iframe, in a page not using winjs).
When it happens, errors can be found in the event log, under "administrative events"
Found this on this link :
http://www.davepaquette.com/archive/2012/09/15/windows-8-store-app-crash-logs.aspx
Jason gives a good solution to this problem in this video (start at time 14:48). In his example, the app was crashing if you had a callback and navigated to a different page before the callback completed. Could this be the case for your app? Any more details on what is going on when you navigate?
For others (since it seems you already know about this!):
To be able to debug easier, use the WinJS.Application.OnError event. Wire up an event handler that dumps out information about the problem before the app crashes.
WinJS.Application.onerror = function (info) {
var err = {
errorMessage: info.detail.errorMessage,
errorUrl: info.detail.errorUrl,
errorLine: info.detail.errorLine,
errorCharacter: info.detail.errorCharacter,
};
Windows.Storage.ApplicationData.current.localFolder
.createFileAsync("crash.txt", Windows.Storage.CreationCollisionOption.openIfExists)
.then(function (file) {
Windows.Storage.FileIO.appendLinesAsync(file, [JSON.stringify(err)]);
});
};
The final stop for exceptions in JavaScript is actually window.onerror; not every exception will get thrown through WinJS.Application.onerror. Try hooking window.onerror directly.