Selenium OpenQA.Selenium.StaleElementReferenceException: 过时的

本文关键字:Selenium 过时 StaleElementReferenceException OpenQA | 更新日期: 2023-09-27 18:33:36

希望有人可以在这个问题上提供帮助...

与级联下拉列表交互时,我不断收到上述错误消息(请参阅标题)。我成功使用的唯一基本修复是"Thread.Sleep"......请参阅下面的代码摘录:

注意我正在传递以下参数:

属性:标识

属性:例如ID123456(下拉菜单的 ID)

参数:汽车(我们要选择的下拉值)

IWebElement element = findMyElement(attribute, attrval);
SelectElement selectElement = new SelectElement(element);
selectElement.SelectByText(parameter);
// dirty code - needs to be re-written
Thread.Sleep(500);
if (new SelectElement(findMyElement(attribute, attrval)).SelectedOption.Text.Equals(parameter))
{
    return "pass";
}

注意2:findMyElement是一个自定义方法(这是一个摘录):

public static IWebElement findMyElement(string attribute, string attrval)
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            switch (attribute.ToLower())
            {
                case "id":
                    wait.Until(ExpectedConditions.ElementExists(By.Id(attrval)));
                    wait.Until(ExpectedConditions.ElementIsVisible(By.Id(attrval)));
                    return driver.FindElement(By.Id(attrval));

正如我在代码注释中所述,无论如何我都可以避免使用 Thread.Sleep,因为我知道这不是推荐的方法。

提前致谢:)

Selenium OpenQA.Selenium.StaleElementReferenceException: 过时的

看起来第一个下拉元素在回发开始时从 DOM 中卸载,并在回发完成后重新加载到 DOM。

当代码尝试在回发期间触摸此元素时,将引发StaleElementReferenceExceptionSleep()调用的工作原理是停止代码在一段时间内接触此元素,恰好该时间段足以完成回发。

理想的解决方案是确定回发何时完成。

哪个谓词只有在回发完成后才会返回 true?将Sleep()替换为等待该谓词返回 true。

例如,如果第二个下拉列表仅出现在回发中,请将Thread.Sleep(500);替换为:

Func<IWebDriver, bool> predicate = (x) =>
{
    try
    {
        IWebElement elementThatOnlyAppearsOnPostback = findMyElement(attribute, attrval);
        return true;
    }
    catch (NoSuchElementException)
    {
        return false;
    }
};
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30)); // or whatever timeout you want to set
wait.Until(predicate);

如果第二个下拉列表已存在,但仅在回发时填充了选项,请将谓词切换为:

Func<IWebDriver, bool> predicate = (x) =>
{
    SelectElement secondDropDown = new SelectElement(findMyElement(attribute, attrval));
    return (secondDropDown.Options.Count > 0);
}