4

我正在使用 Selenium 2 使用 InternetExplorerDriver 测试 asp.net Web 表单页面,但遇到了 StaleElementReferenceException。该页面包含一个(自动回发)下拉列表,我从中选择不同的值。

示例代码:

页:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication.WebForm1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
  <head runat="server">
    <title></title>
  </head>
  <body>
    <form id="form1" runat="server">
    <div>
      <asp:DropDownList ID="ddl" runat="server" AutoPostBack="true">
        <asp:ListItem Text="one"></asp:ListItem>
        <asp:ListItem Text="two"></asp:ListItem>
      </asp:DropDownList>
    </div>
    </form>
  </body>
</html>

(代码隐藏文件仅包含 Visual Studio 自动创建的内容。)

测试夹具代码:

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;

namespace IntegrationTests
{
  [TestFixture]
  public class WebForm1TestFixture
  {
    [Test]
    public void ShouldSelectItemOneThenItemTwo()
    {
      IWebDriver driver = new InternetExplorerDriver(); // Using ChromeDriver causes test to pass...
      driver.Navigate().GoToUrl("http://localhost/<my-virtual-directory-name>/WebForm1.aspx");
      IWebElement list = driver.FindElement(By.Id("ddl"));
      IWebElement itemOne = list.FindElement(By.XPath("option[1]"));
      itemOne.Select();
      list = driver.FindElement(By.Id("ddl"));
      IWebElement itemTwo = list.FindElement(By.XPath("option[2]"));
      itemTwo.Select();
      list = driver.FindElement(By.Id("ddl"));
      itemOne = list.FindElement(By.XPath("option[1]"));// This line causes the StaleElementReferenceException to occur
      itemOne.Select();

      // Some assertion would go here
    }
  }
}

当我运行测试时,我收到以下错误:

OpenQA.Selenium.StaleElementReferenceException: Element is no longer valid
at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebDriver.cs: line 883
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(DriverCommand driverCommandToExecute, Dictionary`2 parameters) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebDriver.cs: line 727
at OpenQA.Selenium.Remote.RemoteWebElement.FindElement(String mechanism, String value) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 570
at OpenQA.Selenium.Remote.RemoteWebElement.FindElementByXPath(String xpath) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 458
at OpenQA.Selenium.By.<>c__DisplayClasse.<XPath>b__c(ISearchContext context) in e:\Projects\WebDriver\trunk\common\src\csharp\webdriver-common\By.cs: line 119
at OpenQA.Selenium.By.FindElement(ISearchContext context) in e:\Projects\WebDriver\trunk\common\src\csharp\webdriver-common\By.cs: line 227
at OpenQA.Selenium.Remote.RemoteWebElement.FindElement(By by) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 267
at IntegrationTests.WebForm1TestFixture.ShouldSelectItemOneThenItemTwo() in WebForm1TestFixture.cs: line 25 

如果我将测试更改为使用 ChromeDriver,则测试通过。在我看来,这意味着它要么是 InternetExplorerDriver 的问题,要么是 Internet Explorer 浏览器本身的问题。有谁知道我可以做些什么以及是否可以解决这个问题(最终用户将在 IE 中使用该站点,因此很遗憾,无法更改浏览器)?


编辑:我正在使用的当前解决方法是Thread.Sleep()在选择列表之后放置一个;这可行,但显然不是理想的解决方案。

4

3 回答 3

3

下面是我最终实现的模式。

在每次item*.Select()我实施了等待之后:

IWait<IWebDriver> wait = new MyCustomWebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(driver => <some-condition-to-wait-for>);

其中 <some-condition-to-wait-for> 是一种确定项目选择是否已完成的方法(例如,通过检查页面上的另一个控件是否已更新,例如

wait.Until(driver => driver.FindElement(By.Id("someLabelId")).Text == "expectedValue")`.

MyCustomWebDriverWait是一个实现IWait<IWebDriver>并几乎与WebDriverWait类相同的类,只是它捕获StaleElementReferenceException以及NotFoundException(这意味着将lastExceptionfrom的类型更改NotFoundExceptionWebDriverException.

您可以在此处阅读 Daniel Wagner-Hall 在 Selenium-users google 组中是如何指出这个方向的。

于 2011-04-21T10:16:14.210 回答
0

由于自动回发,列表元素可能在 DOM 中发生变化。每次选择选项时尝试重新查找列表元素。例如

IWebElement itemOne = driver.FindElement(By.Id("ddl")).FindElement(By.XPath("option[1]"));
  itemOne.Select();
  IWebElement itemTwo = driver.FindElement(By.Id("ddl")).FindElement(By.XPath("option[1]"));
  itemTwo.Select();
于 2011-03-30T09:57:44.077 回答
0

driver.refresh()我在转到它工作正常的页面后发现调用,我的代码是:

        Pages.Login.Goto();
        Browser.Refresh(); <-- refresh the webdriver after going to the page
        Pages.Login.LogInAsRegularUser();
于 2016-01-21T13:16:57.140 回答