【问题标题】:How do I reliably check the current page after navigation in Selenium WebDriver?在 Selenium WebDriver 中导航后如何可靠地检查当前页面?
【发布时间】:2013-06-17 15:00:13
【问题描述】:

在我使用 Selenium WebDriver 和 IEDriverServer.exe 2.32.3.0 进行的 Web 测试中,我需要在导航到某个 URL 后检查当前页面的标题。代码如下:

_webDriver.Navigate().GoToUrl("...");
Assert.That(_webDriver.Title, Is.EqualTo("..."));

这有时有效,但偶尔会中断 - 标题与预期不符(但仍然是之前页面中的标题)。

我在 StackOverflow (C# Webdriver - Page Title assert fails before page loads) 上读到 IWebDriver.Title 属性不会自动等待导航完成(为什么不呢?),但您需要使用 WebDriverWait API 手动等待.

我实现了手动等待标题:

 var wait = new WebDriverWait(_webDriver, TimeSpan.FromSeconds (3.0));
 wait.Until(d => d.Title == expectedTitle);

但是,这有时会等待 3 秒,然后抛出 WebDriverTimeoutException。运行代码的构建代理非常快,而且我正在测试的网站很简单(刚刚开始开发),所以我很确定它真的不需要 3 秒来导航。我注意到在另一个 StackOverflow 问题上,原始发帖人也得到了WebDriverTimeoutException,只是抓住并忽略了它。

我发现该解决方案有点不稳定,因此我尝试了不同的解决方法。我在我的 HTML 中给了<title> 属性一个 ID 并使用了 IWebDriver.FindElement,它应该等待页面完成:

Assert.That(_webDriver.FindElement(By.Id(ViewIDs.Shared._Layout.Title)).Text, Is.EqualTo(page.ExpectedTitle));

起初,这似乎有效。但是,它并不可靠,有时会抛出:

OpenQA.Selenium.NoSuchElementException : Unable to find element with id == _Layout-title
 at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
 at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
 at OpenQA.Selenium.Remote.RemoteWebDriver.FindElement(String mechanism, String value)
 at OpenQA.Selenium.By.FindElement(ISearchContext context)
 at ...

(我也尝试升级到 WebDriver/IEDriverServer 2.33.0.0;但在那个版本中,<title> 标记的文本始终为空...)

因此我的问题。在 Selenium WebDriver 中导航后如何可靠地检查当前页面?有没有好的模式有效?

【问题讨论】:

  • 这是在远程机器上吗?其他驱动程序有什么不同吗?你真的验证过它在本地有效吗?
  • 这是在构建代理上,其中 IEDriverServer 和测试运行器在同一台机器上。这两种方法(显式等待和查找标题元素)在大多数情况下都可以正常工作,无论是本地还是远程。到目前为止,他们只在构建代理上失败了,但是构建代理运行测试的频率远远高于我在本地运行的频率。
  • 不能说它与其他驱动程序有什么不同,我们需要IE才能工作。实际上,我只想知道做我想做的事情的正确方法是什么。此外,它有点难以重现,因为它只是时不时地失败。 (当我在上面说“远程”时,实际上是指“在构建代理上”。)
  • @user1177636:我在导航后尝试断言当前页面有几个原因。首先,我正在尝试实现Page Object pattern。其次,我喜欢早早地失败,并且当导航将我带到一个意想不到的页面时,我宁愿以“错误的页面”失败而不是“找不到元素”。第三,有时我的测试只包括检查导航结果,例如,在导航到 URL '/' 之后,应该显示 LoginPage。或者,点击“退出”后,用户再次被重定向到登录页面。
  • @user1177636:你说得对,必要时等待 3 秒也无妨。但是,当我使用似乎是为此目的设计的 WebDriverWait 类时,它会超时而没有给我正确的标题。

标签: selenium-webdriver


【解决方案1】:

我刚刚用我在CodeProject 上找到的东西解决了这个问题:

private void WaitUntilLoaded()
{
    var wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(%));
    wait.Until(x =>
    {
        return ((IJavaScriptExecutor)this.driver)
        .ExecuteScript("return document.readyState").Equals("complete");
    });
}

根据w3schools,它适用于大多数流行的浏览器。

当我目前在 Firefox 上进行测试时,我在Mozilla's own page 上找到了关于如何识别已加载页面的信息。恕我直言,阅读值得避免龙。

这给了我

wait.Until(p => p.FindElement(
    By.Id("somethingThatIsDisplayedWhenMyAsyncronousStuffIsFinished")
    ).Displayed);

这拯救了我的一天。

【讨论】:

  • 如果在浏览器真正开始导航到另一个页面之前读取document.readyState,是否仍然存在竞争条件?
  • @FabianSchmied 我的代码类似于Driver.Navigate().GoToUrl(...);WaitUntilLoaded();,我 Selenium 处理它是为了在页面之间导航对于测试网络解决方案非常重要。
【解决方案2】:

我遇到了非常相似的问题。我仍然无法说出原因,但通常如果您尝试使用元素而不进行 isElementPresent 检查,它偶尔会失败。我的解决方案有点“昂贵”,但我还没有找到可靠的替代方案。

我的例子是java,应该不难翻译,但我没有库。

    waitForElement("_Layout-title", 45);

然后继续你的代码

    Assert.That(_webDriver.FindElement(By.Id(ViewIDs.Shared._Layout.Title)).Text, Is.EqualTo(page.ExpectedTitle));

这会尝试设定的次数(在本例中为 45 次)来查找元素。一旦 id=_Layout-title 出现,它将继续到下一行代码并执行断言。虽然它并不完美,但它确实让我的测试更加稳定。

【讨论】:

  • 感谢答案,我很高兴我不是唯一一个遇到这个问题的人。但我仍然希望一定有比重试 45 次或等待几秒钟更好的方法。
猜你喜欢
  • 2021-02-01
  • 1970-01-01
  • 2013-09-14
  • 2011-03-11
  • 2017-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多