我使用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()
;这有效,但显然不是一个理想的解决方案。
答案 0 :(得分:3)
以下是我最终实施的模式。
每次item*.Select()
后我都实施了等待:
IWait<IWebDriver> wait = new MyCustomWebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(driver => <some-condition-to-wait-for>);
其中&lt; some-condition-to-wait-for&gt;是一种确定项目选择已完成的方法(例如,通过检查页面上的另一个控件是否已更新,例如
wait.Until(driver => driver.FindElement(By.Id("someLabelId")).Text == "expectedValue")`.
MyCustomWebDriverWait
是一个实现IWait<IWebDriver>
的类,几乎与WebDriverWait类完全相同,只有它捕获StaleElementReferenceException
以及NotFoundException
(这意味着将lastException
的类型从NotFoundException
更改为WebDriverException
。
你可以阅读Daniel Wagner-Hall对Selenium用户谷歌小组here的指示。
答案 1 :(得分:0)
由于autopostback,list元素可能在DOM中发生变化。 每次选择一个选项时,请尝试重新生成列表元素。 E.g。
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();
答案 2 :(得分:0)
我在找到工作正常的页面后发现调用了ini_set('display_errors', 'On'); // display error if occurs any
mkdir(realpath(dirname(__FILE__)).'/'.$_SESSION['user_id']."/testing/",0777, true);
// realpath(dirname(__FILE__)) gives path to you project directory
,我的代码是:
driver.refresh()