StaleElementReferenceException with UIautomator2

Hi Guys,

Since we’ve moved to UIautomator2 framework , “StaleElementReferenceException” makes our execution very sad :slight_smile:

I was wondering how do you workaround this ?

The obvious solution “not to cache” the element and each time execute driver.findElementBy… is standing against the PO concept …

All our elements are Page’s properties annotated with @FindBy , if we will look for them manually each time they are needed , we are missing the entire concept…

I was wonder if there a way to make a refresh for the PageObject and by that to refresh all the cached elements ?

Thanks

1 Like

can you put a sample code here, to reproduce the issue.

 @AndroidFindBy(id = UIStrings.POSITION_FIXED_INCOME_TOTAL)
    private AndroidElement totalMoneyInTitle;


   public void validateTitleIsEqualSubAssets()
    {
        AbstractAppiumConnection.webDriverWait.until(new ExpectedCondition<Boolean>() {
            @Nullable
            @Override
            public Boolean apply(@Nullable WebDriver webDriver) {
                **return totalMoneyInTitle.isDisplayed();//cause to StaleException --> appium server hangs**
            }
        });
        BigDecimal title = getTotalMoneyInTheTitle();
        BigDecimal totalSubAssets = calculateTotalSumOfSubAssetsInTab();
        Assert.assertEquals("Total cash holdings is not equals total tabs",title,totalSubAssets);
    }

I do something like below, and i don’t notice stale element exception. I would suggest make sure you are on the right page and then make a call to isDisplayed().

public void waitForWebElement(WebElement weblement){
try {
new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOf(weblement));
}
catch(Exception ex){

        System.out.println("WebElement "+weblement.toString() +" not found");
    }

}

@igal_epshtein i used similar to @Venkatesh without issues. BUT this is for WEB!

    public Boolean waitElementForVisibility(List<WebElement> el) {
        return waitElementForVisibility(el, 0, 10);
    }

    public Boolean waitElementForVisibility(List<WebElement> el, int num) {
        return waitElementForVisibility(el, num, 10);
    }

    public Boolean waitElementForVisibility(List<WebElement> el, int num, int seconds) {
        WebDriverWait wait = new WebDriverWait(driver, seconds);
        try {
            WebElement element = wait.until(
                    ExpectedConditions.visibilityOf(el.get(num)));
            if (element.isDisplayed())
                return true;
            else
                return false;
        } catch (Exception e) {
            return false;
        }
    }

for Android NATIVE you should use directly:

    @AndroidFindBy(id = "title")
    private List<AndroidElement> dialogTitle;

    public String getDialogTitle() {
        if (dialogTitle.isEmpty())
            return null;
        else
            return dialogTitle.get(0).getText();
    }

where timeout for dialogTitle is set in page init:

PageFactory.initElements(new AppiumFieldDecorator(driver, DEFAULT_WAIT_TIME, SECONDS), this);

but this one doesn’t answer the stalerefernce issue …

The stalereference occurs once the application view is being destroyed and created once again , then the page’s object is pointing to “old” view element which actually doesn’t exist anymore …

I was wonder if there is a way to “refresh” the page object , and to initialise it with new view elements

@igal_epshtein page object does not point to anywhere. element starts finding whenever you call it find not at the moment of page object init.

once you’ve used the page object , it has a reference to view’s object , in case and the last one was recreated you get Stale exception…

@igal_epshtein you are wrong :grinning: . it has reference to object but not elements mentioned in object. Thus whenever e.g. you try to click in page object by element each time it will start looking for element from zero. There is strategy to override this. But you need enable cache strategy which is other story.

@Aleksei not sure you are right :slight_smile:

I’m getting the stale exception on the same line of code always after the view was recreated (some application’s flow)

@igal_epshtein try to see appium logs with following test:

  1. do click to simple text file several times

Result: with every click first command search for element -> then click to element by found element ID.

anyway suggestion: do clicker function and point to it EVERY click in page objects. in clicker when you see stale error do e.g. pause for 100ms and retry click. Limit this e.g. to 5 tries to avoid loop. good luck :slight_smile:

@Aleksei - this is not happens with click only , but every operation on the page (isDisplayed , setText…)

Apium guys should fix this issue for UIAutomator2 package :wink:

1 Like

@igal_epshtein wow something new for me :slight_smile:

Hi ,
Am also facing the same issue for UIAutomator2

I too am facing this issue. If I put the thread to sleep for a second before accessing someElement.isDisplayed(), then I do not get the StaleElementReferenceException, but this dramatically increases test execution time for large tests (it’s also very ugly, I was told not to use sleeps).

There must be another way… :thinking: