2011-02-25 20 views
4

我使用Selenium 2來測試使用InternetExplorerDriver的asp.net web窗體頁,並遇到StaleElementReferenceException。該頁面包含一個(自動回發)下拉列表,我從中選擇不同的值。Selenium 2 StaleElementReferenceException當使用DropDownList與AutoPostBack與InternetExplorerDriver

示例代碼:

頁:

<%@ 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()已經選擇了列表之後;這工作,但顯然不是一個理想的解決方案。

回答

3

下面是我最終實現的模式。

每個item*.Select()後,我已經實現了一個等待:

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

凡<一些條件,以等待換>是確定項目的選擇已經完成(例如,通過檢查的方式該頁面上的其他控件已更新,如

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

MyCustomWebDriverWait是實現IWait<IWebDriver>,幾乎等同於WebDriverWait類只有它捕獲了StaleElementReferenceException以及NotFoundException(這意味着將lastException的類型從NotFoundException更改爲WebDriverException

您可以閱讀Daniel Wagner-Hall在Selenium用戶谷歌組here上的指示。

+0

那麼你是否每次使用這個函數調用FindElement? – 2017-09-05 15:20:34

+0

@VictorioBerra嗯,我不記得了 - 這是很久以前的事了,對不起! – Zoodor 2017-10-05 15:56:48

0

由於autopostback,列表元素可能在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(); 
+0

感謝您的答覆,但我已經做了代碼示例上面...(除非我生氣,這不是完全不可能) – Zoodor 2011-04-12 08:06:15

0

我發現要在頁面,它工作得很好以後打電話driver.refresh(),我的代碼是:

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