如何解决 PyTest 中的陈旧元素异常

How to work around stale element exception in PyTest

在下面的测试中,我点击了 this link 上的每张卡片并查看标题文本是否匹配。我 运行 进入 StaleElementReferenceException 我的假设是 internships 变量在点击卡片后变得陈旧,即使我使用 self.driver.back() 到 return 到我点击的页面.

是否有解决此类问题的方法?还是我需要为每张卡创建单独的测试?如果是这样,PyTest 是否有一个 built-in 模块可以让我们轻松创建单独的测试?

def test_internship_links(self):
    num_title_mismatch = 0
    title_mismatches = {}
    internships_xpath = (
        "//div[@id='related_projects']//div[@class='project-description']/h3"
    )
    internships = self.driver.find_elements(By.XPATH, internships_xpath)
    for internship in internships:
        outer_title = internship.text
        internship.click()
        inner_title = self.driver.find_element(
            By.XPATH, "//div[@class='primary']//h1"
        ).text
        if inner_title != outer_title:
            num_title_mismatch += 1
            title_mismatches[outer_title] = inner_title
        self.driver.back()
    assert (
        num_title_mismatch == 0
    ), f"\n{num_title_mismatch} title mismatch(es) found:\n{title_mismatches}"

错误回溯:

________________________________________________________________________ TestSearchInterships.test_internship_links ________________________________________________________________________

self = <test_search_internships.TestSearchInterships object at 0x1081bfe90>

    def test_internship_links(self):
        num_title_mismatch = 0
        title_mismatches = {}
        internships_xpath = (
            "//div[@id='related_projects']//div[@class='project-description']/h3"
        )
        internships = self.driver.find_elements(By.XPATH, internships_xpath)
        for internship in internships:
>           outer_title = internship.text

tests/test_search_internships.py:41: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../.local/share/virtualenvs/converge-testing-PXQ7_xev/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py:81: in text
    return self._execute(Command.GET_ELEMENT_TEXT)['value']
../../../.local/share/virtualenvs/converge-testing-PXQ7_xev/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py:693: in _execute
    return self._parent.execute(command, params)
../../../.local/share/virtualenvs/converge-testing-PXQ7_xev/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py:338: in execute
    self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

如果页面上的 DOM(文档对象模型)操作暂时导致元素无法访问,则可能会发生此问题。

我可以看到 2 种可能的解决方法来解决您的问题。

1) 您可以再次导航到 link,而不是使用 self.driver.back() 到 return 的页面。例如:driver.get('your_url')

2) 在最终抛出异常之前,您可以尝试在循环中多次访问该元素。您可以查看 Darrel Grainger 的解决方案 here.

如果对我有帮助请点赞=)

计算元素的数量并使用范围而不是遍历元素本身对我来说是个窍门。下面是工作代码。

def test_internship_links(self):
    num_title_mismatch, title_mismatches = 0, {}
    internships = self.driver.find_elements(
        By.XPATH, "//div[@id='related_projects']//a"
    )
    # xpath is indexed from 1, not 0
    for int_num in range(1, len(internships) + 1):
        internship_xpath = f"//div[@id='related_projects']//a[{int_num}]//div[@class='project-description']//h3"
        internship = self.driver.find_element(By.XPATH, internship_xpath)
        outer_title = internship.text
        internship.click()
        inner_title_xpath = "//div[@class='primary']//h1"
        inner_title = self.driver.find_element(By.XPATH, inner_title_xpath).text
        if inner_title != outer_title:
            num_title_mismatch += 1
            title_mismatches[outer_title] = inner_title
        self.driver.back()
    assert_str = (
        f"\n{num_title_mismatch} title mismatch(es) found:\n{title_mismatches}"
    )
    assert num_title_mismatch == 0, assert_string