1

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.

Darwin Allen
  • 190
  • 4
  • 15

1 Answers1

2

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.

Community
  • 1
  • 1
Petr Janeček
  • 37,768
  • 12
  • 121
  • 145
  • Yeah it appears that the `customSection` as well as several other elements are getting affected due to more than one refresh of the page. In other words, an element may go stale twice when loading the page. I checked out our NeverStaleWebElement example but I worry that I'll get stuck in an infinite loop or a race condition situation (if exit after an implied time is added and the page loads slowly). As for the stack trace itself, I'm assuming it's not possible to get the name of the element that's gone stale reported back? – Darwin Allen Oct 23 '13 at 18:25
  • @DarwinAllen Unfortunately, no. Though it could be possible to obtain the 'By' object that was used to find the element via some hacky code. – Petr Janeček Oct 23 '13 at 18:46