【问题标题】:C# Selenium 'ExpectedConditions is obsolete'C# Selenium 'ExpectedConditions 已过时'
【发布时间】:2018-09-26 17:25:11
【问题描述】:

当尝试使用 ExpectedConditions 显式等待某个元素变为可见时,Visual Studio 会警告我它现在已过时,很快就会从 Selenium 中删除。

实现相同结果的当前/新方法是什么?

var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 30));
var element = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("content-section")));

【问题讨论】:

  • 您使用的 Selenium 版本是什么?

标签: c# selenium webdriver


【解决方案1】:

检查您安装了哪个版本的 Selenium.Support 和 Selenium.WebDriver NuGet 包。

我现在在最新版本 3.11.2 中遇到了同样的问题。我降级到 3.10.0 并解决了问题。

【讨论】:

  • 是的,我使用的是最新版本,我昨晚刚刚用 NuGet 添加了它。 Selenium.Support 也是如此。我宁愿不降级,我想了解新方法是什么,这样我就可以在我的项目中使用未来的版本。
  • 如果你想看我的回答,如果你想使用新的和未来的版本,我想通了。
  • 如果它过时的降级不是一个好的解决方案。理想情况下,您会使用新的方法。
  • 如果目前没有时间重写代码,降级实际上是一种可以接受的解决方案。
  • 表现得像鸵鸟有时也是一个很好的解决方案。
【解决方案2】:

如何使用最新版本的 Selenium 解决此问题。

使用 NuGet,搜索 DotNetSeleniumExtras.WaitHelpers,然后将该命名空间导入您的类。现在你可以这样做了:

var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 30));
var element = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.Id("content-section")));

并且IDE中的警告将消失。

【讨论】:

  • 请注意,该项目没有所有者。我不知道他们为什么从 Selenium 中删除它,但目前不会对 DotNetSeleniumExtras 存储库进行更新。
  • 他们删掉了它,因为它是 Java 实现的副本,难以维护且实现不佳。 jimevansmusic.blogspot.com/2018/03/…
  • 它还带有一个很棒的工具,叫做“PageObjects”。很好用。
【解决方案3】:

如果您不想下载额外的 NuGet 包,可以很容易地声明自己的函数(或条件),尤其是使用 lambda 表达式,例如

var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 30));
var element = wait.Until(condition =>
{
    try
    {
        var elementToBeDisplayed = driver.FindElement(By.Id("content-section"));
        return elementToBeDisplayed.Displayed;
    }
    catch (StaleElementReferenceException)
    {
        return false;
    }
    catch (NoSuchElementException)
    {
        return false;
    }
});

这也是非常通用的,因为现在可以计算任何类型的布尔表达式。

【讨论】:

  • 我喜欢它的多功能性,但如果我使用多个等待,这可能需要更多的代码行。
  • 如果你把它包装在一个函数中,肯定不会有更多的代码吗?
  • 太棒了! @Stevieboy84,如何将其包装成一个函数?
  • 如何将其包装到一个函数中并将其应用于不同元素的多个等待?
  • 创建一个接收By作为参数并返回bool的函数
【解决方案4】:

这很简单。只是改变 Wait.Until(ExpectedConditions.ElementIsVisible(By.Id("content-section")));

Wait.Until(c => c.FindElement(By.Id("content-section")));

【讨论】:

  • 虽然替换会起作用,但还是有区别的。使用 ElementIsVisible 等待而不抛出任何异常。 FindElement 版本会抛出一个内部 NoSuchElementException,如果您的 IDE 因抛出的异常而中断,这会使调试复杂化。
  • 附带说明,默认情况下等待实用程序 ignores NoSuchElementExceptionselenium.dev/documentation/en/webdriver/waits
【解决方案5】:

改成匿名函数的答案是最正确的。或者编写您自己的、需要的、等待条件的类。

在上述显式场景中使用匿名函数的示例如下:

var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 30));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(ElementNotVisibleException));
var element = wait.Until(() =>
{
    var e = Driver.FindElement(By.Id("content-section"));
    if(e.Displayed)
        return e;
});

此时,函数本身可能会在您可以调用的解决方案中的某个类中自行关闭。这样做的好处是您可以根据需要进行修改;我见过几个案例,其中非常糟糕的网站最终会破坏 ExpectedConditions 的工作方式,并且通过团队编写我们自己的函数来解决。

根据 C# 贡献者:

关于 ExpectedConditions,再一次,这是一个补充 是在 .NET 中创建的,仅仅是因为“Java 拥有它”。当时的 Java中的ExpectedConditions类被创建,创建的语法 一个 lambda 函数(或类似的函数)特别 晦涩难懂。在这种情况下,一个助手类 Java 绑定很有意义。但是,C# 不是 Java。在 C# 中, 创建 lambda 函数的语法(“匿名方法”在 微软文档的语言)已经被 C# 很好理解 开发人员多年,是他们武器库中的标准工具。

在这种情况下,代码冗长的问题确实有一些优点,但是 因为等待条件很少是千篇一律的,这将是一个很大的 用户开发自己的条件类的更清洁的方法 有他们感兴趣的等待条件。然而,这是 用户厌恶的东西。此外,一个想法 特定等待条件实现的“标准”集合 从表面上看似乎是个好主意,但有很多 用户希望任何给定条件起作用的方式的变化。有一个 收集等待条件可能是件好事,但 Selenium 项目不适合它。

Rantings of a Selenium Contributor

【讨论】:

  • 谢谢。显然 - 由于几个不同的原因 - 导入“DotNetSeleniumExtras.WaitHelpers”是不是最好的解决方案。您的示例 - 或 Everton Rocha 的示例 above 应该是“首选”方法。
【解决方案6】:

需要 NuGet - DotNetSeleniumExtras.WaitHelpers

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.XPath("")));

我刚刚演示了元素可点击事件。同样,其他事件也可以与所需参数一起使用。

【讨论】:

    【解决方案7】:

    基于Rob F.'s answer,我在我的项目中添加了扩展方法。 (其实我加了两个,WaitUntilVisible(...)WaitUntilClickable(...)。)

    这些返回元素,而不是布尔,所以它更像Wait.Until(ExpectedConditions...)

    // use: element = driver.WaitUntilVisible(By.XPath("//input[@value='Save']"));
    public static IWebElement WaitUntilVisible(
        this IWebDriver driver,
        By itemSpecifier,
        int secondsTimeout = 10)
    {
        var wait = new WebDriverWait(driver, new TimeSpan(0, 0, secondsTimeout));
        var element = wait.Until<IWebElement>(driver =>
        {
            try
            {
                var elementToBeDisplayed = driver.FindElement(itemSpecifier);
                if(elementToBeDisplayed.Displayed)
                {
                    return elementToBeDisplayed;
                }
                return null;
            }
            catch (StaleElementReferenceException)
            {
                return null;
            }
            catch (NoSuchElementException)
            {
                return null;
            }
        });
        return element;
    }
    

    【讨论】:

      【解决方案8】:

      以下 C# 代码适用于我:

      new WebDriverWait(webDriver, TimeSpan.FromSeconds(10)).Until(c => c.FindElement(By.Id("name")));
      

      【讨论】:

        【解决方案9】:

        您可以使用 NuGet 包 Gravity.Core - 它由 Gravity API 社区维护,它包含的不仅仅是 ExpectedConditions 类。

        如何使用

        1. 使用 NuGet 包管理器下载 NuGet。
        2. 添加using OpenQA.Selenium.Extensions

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-22
          • 2020-01-26
          • 2021-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多