页面刷新期间 selenium.common.exceptions.StaleElementReferenceException [英] selenium.common.exceptions.StaleElementReferenceException during page refresh

查看:34
本文介绍了页面刷新期间 selenium.common.exceptions.StaleElementReferenceException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

页面包含一些数据(包含几行的表格).有刷新"按钮,可在不重新加载静态数据(ajax)的情况下重新加载和重绘页面上的某些元素.

Page contains some data (table with few rows). There is 'refresh' button which reload and redraw some elements on page without reloading static data (ajax).

我正在尝试为该页面创建适当的测试,但有时会遇到 StaleElementReferenceException.

I'm trying to create proper test for that page, but getting StaleElementReferenceException sometimes.

我的代码(python):

My code (python):

from selenium import webdriver
browser=webdriver.Firefox()
browser.get('http://mytisite')
browser.implicitly_wait(10)
browser.find_element_by_id('start').click()
while browser.find_element_by_id('status').text!='Done':
    browser.find_element_by_id('refresh').click()
    for row in browser.find_elements_by_class_name('datarow'):
        if not is_correct(row.text):
           print "incorrect"
    time.sleep(10)

5 次迭代中的 1 次在if not is_correct(row.text)"行失败:

1 of 5 iterations fails on line "if not is_correct(row.text)":

selenium.common.exceptions.StaleElementReferenceException: 
 Message: u'Element not found in the cache - perhaps the page 
 has changed since it was looked up' ; Stacktrace: Method 
 fxdriver.cache.getElementAt threw an error in 
 resource://fxdriver/modules/web_element_cache.js 

主要问题:页面已经包含以前的数据,所以我在 ajax 刷新和 webdriver 的 find_elements_by_class_name('datarow') 元素查询之间发生了竞争.

Main problem: page already contains previous data, so I'm getting race between ajax refresh and webdriver's element query of find_elements_by_class_name('datarow').

如何正确解决ajax刷新和webdriver之间的竞争?谢谢.

How can I proper solve race between ajax refresh and webdriver? Thanks.

推荐答案

恐怕我无法帮助您进行 Python 绑定.但是,我可以帮助您提供有关 WebDriver 的一般建议和一些 Java 片段,这些片段可能会帮助您(其他人)找到他们的 Python 等价物.在 Selenium 中,您可以做很多处理 AJAX 的事情.

I am afraid, I cannot help you with python binding. However I can help you with general advice on WebDriver and some Java snippets that may help you (others) lead to find their python equivalent. There are a bunch of things you can do handle AJAX in Selenium.

1.隐式等待 - 这将告诉网络驱动程序轮询 DOM 一段时间.

1. Implicit waits- This will tell web driver to poll the DOM for a certain period.

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

2.显式等待 - 我更喜欢这些!可以将这些与隐式等待结合使用.您可以告诉 WebDriver 等待特定条件.您需要使用 WebDriverWait 来使用显式等待.

2. Explicit waits - I prefer these! One can use these in conjunction with implicit waits. You can tell WebDriver to wait for certain condition. You need to use WebDriverWait to use explicit waits.

WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("refresh")));

ExpectedConditions 免费提供了许多等待条件,我觉得它非常有用.

ExpectedConditions provides many wait conditions for free and I find it extremely useful.

如果我用 Java 编写上面的代码片段,我会在下面做.注意我是在编辑器中写的,所以它应该可以编译.我想这会让你对 WebDriverWait 的使用有所了解.

If I were to write your above code snippet in Java, I would do below. Note I wrote this in an editor, so it should compile. I guess this will give you an idea on the use of WebDriverWait.

WebDriverWait wait = new WebDriverWait(driver, 60/*timeout in seconds*/);
ExpectedCondition<Boolean> untilIFindStatus = ExpectedConditions
                    .elementToBeSelected(By.id("status"));
while (wait.until(untilIFindStatus)) {
        WebElement refresh = wait.until(ExpectedConditions
                        .elementToBeClickable(By.id("refresh")));
        refresh.click();
        List<WebElement> allRows = wait.until(ExpectedConditions
                .presenceOfAllElementsLocatedBy(By.className("datarow")));
             for (WebElement row : allRows) {
                if (row.getText().equals("awesome"))
                    System.out.println("do something");
             }
 }

最后,根据我的经验,许多现代 AJAX 应用程序都使用 jQuery.多年来,我已经成功地使用 jQuery.active 标志来检查页面是否已加载.您可以将其与纯 javascript document.readyState 结合使用.这是我在每次点击"我的 AJAX 应用程序后使用的一般方法.

Lastly, in my experience many modern AJAX applications use jQuery. I have used jQuery.active flag over several years successfully to check whether the page is loaded or not. You can combine that with plain javascript document.readyState. This is the general method I use for wait after every 'click' for my AJAX apps.

ExpectedCondition<Boolean> jQueryActive_toBeZero = new ExpectedCondition<Boolean>()   {
        public Boolean apply(WebDriver driver) {
           try {
            return ((Long) jsExecutor
                .executeScript("return jQuery.active") == 0) ? true
                            : false;
         } catch (WebDriverException e) {
             log.debug("It looks like jQuery is not available on the page, skipping the jQuery wait, check stack trace for details");
             return true; //skip the wait
         }
           }
       };
ExpectedCondition<Boolean> document_readyState_toBeComplete = new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver driver) {
          return jsExecutor.executeScript("return document.readyState")
             .toString().equals("complete") ? true : false;
         }
     };
    wait.until(jQueryActive_toBeZero);
    wait.until(document_readyState_toBeComplete);

这篇关于页面刷新期间 selenium.common.exceptions.StaleElementReferenceException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆