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();