【问题标题】:Selenium c# - OpenQA.Selenium.StaleElementReferenceException: stale element reference: element is not attached to the page documentSelenium c# - OpenQA.Selenium.StaleElementReferenceException:过时的元素引用:元素未附加到页面文档
【发布时间】:2015-02-07 07:15:40
【问题描述】:

希望有人可以帮助解决这个问题...

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

注意我传递了以下参数:

属性:ID

attrval:例如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));

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

提前致谢:)

【问题讨论】:

  • 哪一行抛出异常?选择下拉列表时,您的应用程序会发生什么?页面是否发生了变化?添加了哪些新元素?是否发送了任何新请求?
  • 这里抛出异常(没有thread.sleep) if (new SelectElement(findMyElement(attribute, attrval)).SelectedOption.Text.Equals(parameter))
  • 关于页面本身,因为它是一个级联下拉菜单,下拉菜单中的可选选项将更新,例如如果我在第一个下拉菜单中选择汽车,第二个会询问颜色。在后台中注意页面在选择第一个下拉列表中的值 span>时,页面返回
  • 如果可能的话,您能否提供您的 html,并且在执行此操作之前您是否使用不同的操作来回导航?
  • 在前端 aspx 上,当第一个下拉值被选中时,会进行以下调用: OnDropDownSelectedIndexChanged="..._DropDownSelectedIndexChanged" 这又会定位第二个下拉列表并重新绑定数据

标签: c# selenium selenium-webdriver


【解决方案1】:

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

StaleElementReferenceException 在您的代码在回发期间试图触及该元素时被抛出。 Sleep() 调用的工作原理是让您的代码在一段时间内停止接触该元素,这段时间恰好足以完成回发。

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

什么谓词只会在回发完成后才返回 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2023-03-24
    • 1970-01-01
    • 2022-08-17
    • 2021-11-25
    相关资源
    最近更新 更多