Reputation: 300
I've done some pretty thorough digging and am having trouble nailing down exactly which element is causing this exception to be thrown. I'm using Java and Selenium 2 and have recently taken over a fairly large test suite to maintain. Instead of blindly placing fluent waits in and around the failing lines of code, I'd like to actually determine which elements are causing the issue.
I've though about breaking a bunch of the single-line logic into more lines of code to help nail it down but since these random failure are intermittent and all over the place, I'm trying to find a way to get the actual name of the element or locator in the stack trace.
Is this possible or do I have to do a bunch of refactoring on the code end of things?
Here is an example stack trace:
Starting ChromeDriver (v2.3) on port 24902
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=30.0.1599.101)
(Driver info: chromedriver=2.3,platform=Mac OS X 10.8.5 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 5 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.33.0', revision: '4ecaf82108b2a6cc6f006aae81961236eba93358', time: '2013-05-22 12:00:17'
System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.8.5', java.version: '1.7.0_21'
Session ID: f3e5d2c3eb54afc2fcaacc1c663435e9
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=chrome, chrome={chromedriverVersion=2.3}, rotatable=false, locationContextEnabled=true, version=30.0.1599.101, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=false, webStorageEnabled=true, nativeEvents=true, applicationCacheEnabled=false, takesScreenshot=true}]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:191)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
at org.openqa.selenium.remote.RemoteWebElement.findElements(RemoteWebElement.java:187)
at org.openqa.selenium.remote.RemoteWebElement.findElementsByCssSelector(RemoteWebElement.java:240)
at org.openqa.selenium.By$ByCssSelector.findElements(By.java:417)
at org.openqa.selenium.remote.RemoteWebElement.findElements(RemoteWebElement.java:163)
at com.xmatters.webui.pages.home.developer.managerelevanceengines.formdetails.layoutsections.CustomSectionScreen.rowPropertyIsInCustomSection(CustomSectionScreen.java:54)
at com.xmatters.webui.pages.home.developer.managerelevanceengines.formdetails.layoutsections.CustomSectionScreen.editNameForProperty(CustomSectionScreen.java:90)
at com.xmatters.webdriver.tests.REBProperties_BooleanTest.confirmBooleanPropertyNameCanBeEditedOnLayoutTab(REBProperties_BooleanTest.java:526)
The code on the suspect line is in this helper function.
Line 54 is the line containing List<WebElement>...
public Integer rowPropertyIsInCustomSection(String propertyName) {
wait.until(ExpectedConditions.presenceOfElementLocated(customSectionLocator));
WebElement customSection = driver.findElement(customSectionLocator);
//wait until properties are present in custom section
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(propertiesInCustomSectionLocator));
List<WebElement> propertiesInCustomSection = customSection.findElements(propertyNameLocatorInCustomSection);
By propertyNameLoc = By.id("propertyName");
for (int i = 0; i < propertiesInCustomSection.size(); i++) {
wait.until(ExpectedConditions.visibilityOfElementLocated(propertyNameLoc));
String propName = propertiesInCustomSection.get(i).findElement(propertyNameLoc).getText();
if (propName.equals(propertyName)) {
return i;
}
}
return null;
Apologies if this has been answered elsewhere but I'm having a tough time nailing this one down with so little to work with in the stack trace. This code was all written by someone else so dissecting it piece by piece is kind of a last resort for me at the moment.
Thanks in advance for any pointers.
Darwin.
Upvotes: 1
Views: 659
Reputation: 38444
I'm pretty sure it's the customSection
element.
WebElement#findElements()
will definitely not throw a StaleElementReferenceException
on any of the freshly found elements (that would be a bad Selenium bug).
As said in WebElement
docs, it will throw on most of the methods called on a previously found WebElement
. Therefore when you try to invoke findElements()
on an element, it performs a freshness check which fails for some reason.
Before searching for customSection
, try to wait for some of the its properties to show up. It's possible that when adding properties to the section, the element is discarded and replaced by a new one. Or you can try one of the techniques described here, namely the NeverStaleWebElement
.
Upvotes: 2