Selenium 2 StaleElementReferenceException使用DropDownList和AutoPostBack使用InternetExplorerDriver时

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

示例代码:

页:

       

(代码隐藏文件只包含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//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.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() ; 这有效,但显然不是一个理想的解决方案。

以下是我最终实施的模式。

在每个item*.Select()我实现了一个等待:

 IWait wait = new MyCustomWebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(driver => ); 

其中是一种确定项目选择已完成的方式(例如,通过检查页面上的另一个控件是否已更新,例如

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

MyCustomWebDriverWait是一个实现IWait的类,几乎与WebDriverWait类相同,只捕获StaleElementReferenceException以及NotFoundException (这意味着将lastException的类型从NotFoundException更改为WebDriverException

你可以在这里看看Daniel Wagner-Hall在Selenium用户谷歌小组的指导方向。

由于autopostback,list元素可能在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(); 

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

  Pages.Login.Goto(); Browser.Refresh(); <-- refresh the webdriver after going to the page Pages.Login.LogInAsRegularUser();