Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Selenium与Python:Stale元素引用异常_Python_Selenium_Automation - Fatal编程技术网

Selenium与Python:Stale元素引用异常

Selenium与Python:Stale元素引用异常,python,selenium,automation,Python,Selenium,Automation,从开始工作,在迁移后立即运行功能测试时,我当前遇到了“StaleElementReferenceException”。以下是错误的全文: ERROR: test_start_and_retrieve_list (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "funct

从开始工作,在迁移后立即运行功能测试时,我当前遇到了“StaleElementReferenceException”。以下是错误的全文:

ERROR: test_start_and_retrieve_list (__main__.NewVisitorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "functional_tests.py", line 53, in test_start_and_retrieve_list
    rows = table.find_elements_by_tag_name('tr')
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 237, in find_elements_by_tag_name
    return self.find_elements(by=By.TAG_NAME, value=name)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 527, in find_elements
    {"using": by, "value": value})['value']
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 493, in _execute
    return self._parent.execute(command, params)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webdriver.py", line 256, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <table id="id_list_table"> stale: either the element is no longer attached to the DOM or the page has been refreshed


----------------------------------------------------------------------
Ran 1 test in 8.735s

FAILED (errors=1)

如何配置测试以防止出现这种情况?Selenium自己的页面说,当页面刷新时可能会出现此问题,但这是应用程序逻辑的一个必要部分,因为到目前为止它已经配置好了。

我已经使用Selenium一段时间了,所以我理解了陈旧元素异常的困难。虽然不是完美的,但是selenium提供了一系列命令来允许网站加载完成。不幸的是,它并不完美,因为每次运行时加载可能需要不同的时间,但这些都是selenium提供的工具。

我没有使用python,但使用过java/selenium。但是,我可以给你一个克服陈腐的想法

通常,如果在启动webelement之后元素属性或某些内容发生了更改,我们将得到陈旧的异常。例如,在某些情况下,如果用户尝试在同一页面上单击同一元素,但在页面刷新后,会出现staleelement异常

为了克服这个问题,我们可以创建新的webelement,以防页面被更改或刷新。下面的代码可以给你一些想法。(它是用java编写的,但概念是一样的)

例如:

webElement element = driver.findElement(by.xpath("//*[@id='StackOverflow']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
为了克服这个问题,我们可以将xpath存储在某个字符串中,并使用它创建一个新的webelement

String xpath = "//*[@id='StackOverflow']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.fineElement(by.xpath(xpath)).click();   //This works
另一个例子:

for(int i = 0; i<5; i++)
{
  String value = driver.findElement(by.xpath("//.....["+i+"]")).getText);
  System.out.println(value);
} 

for(int i=0;i要防止元素过时,请在当前页面上放置一个新元素,点击链接并等待该元素不再可用。然后等待新页面上的元素出现

    script_to_execute = """
            var new_element = document.createElement('span');
            new_element.setAttribute('id', 'wait4me');
            document.body.appendChild(new_element);"""
    self.driver.execute_script(script_to_execute)
    self.driver.find_element_by_xpath("{}".format(locator)).click()
    WebDriverWait(self.driver, self.time_out).until (
                lambda x: not x.find_elements_by_id("wait4me")) 
当循环在更新的页面完全加载之前启动时会发生此问题。尤其是在应用程序或表单中更新页面时。 一种解决方法是在当前页面上放置一个元素,然后更新并使用WebDriverWait语句,直到再也找不到该元素为止。
然后启动循环。(否则在循环过程中会发生重新加载…

我读了与您相同的书,遇到了相同的问题(来自的解决方案对我不起作用)。 我是这样解决的

问题 每当你们试图访问一个过时的对象时,就会抛出异常。所以我们必须等待这个异常不再被抛出的情况

我的解决方案 我创建了一个方法,等待我的操作通过

from selenium.common.exceptions import StaleElementReferenceException
[...]
def stale_aware_for_action(self, action):
    while(True):
        try:
            action()
            break
        except StaleElementReferenceException:
            continue
在测试方法中,我定义了要等待完成的操作:

def test_can_start_a_list_and_retrieve_it_later(self):
    [...]
    def insert_second_item_to_inputbox():
        inputbox = self.browser.find_element_by_id('id_new_item')
        inputbox.send_keys('Use peacock feathers to make a fly')
        inputbox.send_keys(Keys.ENTER)

    self.stale_aware_for_action(insert_second_item_to_inputbox)

    def check_for_first_item():
        self.check_for_row_in_list_table('1: Buy peacock feathers')
    def check_for_second_item():
        self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')

    self.stale_aware_for_action(check_for_first_item)
    self.stale_aware_for_action(check_for_second_item)
添加以下导入:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
更改这些行

inputbox.send_keys(Keys.ENTER)
self.check_for_row('1: Buy peacock feathers')
致:


这就用更“合理”的东西代替了时间。sleep(1)

我在这里写了一个完整的答案:我有同样的问题——查找行,而不是表。通过标签名称(“tr”)查找元素,我们可以使用self.browser.find元素名称(“tr”)。换句话说,我们可以在每次尝试查找元素时使用浏览器,而不是使用元素查找其他元素。Santhosh,感谢您的建议。但是,在实现此xpath解决方案后,我收到与以前相同的错误,即我引用的元素过时。好的……这是通用解决方案如果你不介意的话,你可以再次检查你的更新代码,确认你只有在页面稳定后才创建了webelement(例如刷新后/不使用之前创建的webelement)。
inputbox.send_keys(Keys.ENTER)
self.check_for_row('1: Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)

WebDriverWait(self.browser, 10).until(
            expected_conditions.text_to_be_present_in_element(
                (By.ID, 'id_list_table'), 'Buy peacock feathers'))

self.check_for_row('1: Buy peacock feathers')