【问题标题】:C# Selenium WebDriverWait.IgnoreExceptionTypes does not workC# Selenium WebDriverWait.IgnoreExceptionTypes 不起作用
【发布时间】:2017-11-06 19:33:45
【问题描述】:

我正在尝试使用 Selenium WebDriverWait 类型来等待页面完全加载,然后再检查元素是否存在。我尝试了两种不同的方式。

第一个方法使用IgnoreExceptionTypes,然后在Until 方法中调用FindElement。这会立即抛出 NoSuchElementException 而无需等待。我希望这会继续尝试查找元素,直到超时,同时忽略 NoSuchElementException。它似乎不以这种方式工作。为什么方法 1 不起作用?

第二种方法使用 ExpectedConditions.ElementExists,并且似乎等待正确。

driver.Navigate().GoToUrl("http://www.google.com");
var myId = "myId";

//Method 1
var wait1 = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait1.IgnoreExceptionTypes(typeof(NoSuchElementException));

//Does not wait. Immediately throws NoSuchElementException
var result1 = wait1.Until(x => x.FindElement(By.Id(myId)));

//Method 2    - works as expected
var wait2= new WebDriverWait(driver,TimeSpan.FromSeconds(10))
    .Until(ExpectedConditions.ElementExists(By.Id(myId)));

【问题讨论】:

  • 你在使用页面对象模型吗?
  • 我不这么认为..我的问题是除了创建驱动程序之外的所有代码

标签: c# selenium-webdriver webdriver selenium-chromedriver


【解决方案1】:

回答新改述的问题...

所以我一直这样做。我使用页面对象模型来编写自动化,所以这很适用,但即使您不使用页面对象模型,您仍然可以使用它。

基本概念是......你找到一个最后加载的元素并等待该元素。此时,您知道页面已完成加载,您的脚本可以继续执行,而不必担心与页面上尚未完成加载的某些元素进行交互。

警告...我到底怎么知道哪个元素是最后加载的?我不知道。你基本上做出一个猜测(希望是有根据的猜测)并使用它直到它失败。如果您的页面不是非常动态,那么只需选择任何元素。如果页面的某个部分加载较晚,请在页面的该部分中选择一个元素。

这就是我通常的情况。我为某个页面编写了一个页面对象。我在页面上选择了一个独特的元素并将其声明为By waitForLocator。现在,当我想等待页面完成加载时,我会调用

By waitForLocator = By.Id("myId");
new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementIsVisible(waitForLocator));

现在我(相当)确信页面已完成加载,我开始为页面对象编写方法等等。我编写了一个脚本,该脚本使用该页面对象并根据我的测试用例与页面交互,然后运行该脚本。希望我选好了我的waitForLocator。如果我没有,在脚本运行期间的某个时候我会遇到一些异常,因为某些元素没有完全加载(它在我选择的元素之后加载)。因此,我将waitForElement 更改为我刚刚与之交互的引发异常的元素,现在我应该对最后一个加载元素有更好的猜测。您基本上重复此过程,直到不再出现异常为止。

您可能会说,这是一种非常随意的方式。它看起来确实比实际情况更随意。如果您知道您的网站和页面,您将做出一个很好的初步猜测。我必须更改一次猜测是非常罕见的,而且我必须多次更改它是非常罕见的。也就是说,改变它真的很容易。您已经有了引发异常的元素的定位器,只需将其粘贴到 waitForLocator 的声明中即可。

因此,您可能遇到的一个例外是,如果您正确选择了 waitForLocator 并且 在页面加载后,您单击页面上的某个元素会动态加载其他部分的页面。这种情况超出了等待页面加载的范围。在这种情况下,您将不得不构建另一个等待,等待页面的新加载部分在执行单击后完成加载。不会影响页面加载机制。


额外的 cmets

回过头来阅读您的问题后,这里有一些额外的信息可以让您的生活更轻松。

您最初的问题有一种方法,我在下面简化/修改了该方法以证明这一原则

public void ClickElementById(RemoteWebDriver driver, string id)
{
    driver.FindElement(By.Id(id)).Click();
}

这个方法的编写方式,你强迫自己为每个定位器类型、ID、名称、CSS 选择器、XPath 等创建一个方法。而不是传入一个字符串,而是传入一个By 定位器。

public void ClickElement(RemoteWebDriver driver, By locator)
{
    driver.FindElement(locator).Click();
}

现在有了这种新方法,它完全灵活。您可以传入任何定位器类型,它会起作用。要调用它,您可以使用类似

ClickElement(driver, By.Id("someId"));

【讨论】:

  • 我很困惑。您发布的方法将驱动程序和 id 作为参数,但您正在谈论自定义等待时间和现有元素。您可能需要澄清您实际在做什么的问题,因为它似乎与您在此处提出的问题不同。
  • 根据新信息更新了我的答案
猜你喜欢
  • 2016-04-29
  • 2011-12-09
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
相关资源
最近更新 更多