Selenium 2 StaleElementReferenceException lors de l’utilisation de DropDownList avec AutoPostBack avec InternetExplorerDriver

J’utilise Selenium 2 pour tester une page de formulaires Web asp.net à l’aide d’InternetExplorerDriver et rencontre une exception StaleElementReferenceException. La page contient une liste déroulante (post-publication automatique), à ​​partir de laquelle je sélectionne différentes valeurs.

Exemple de code:

Page:

       

(Le fichier code-behind ne contient rien d’autre que les éléments créés automatiquement par Visual Studio.)

Code de l’appareil de test:

 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 } } } 

Lorsque je lance le test, l’erreur suivante apparaît:

 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(Ssortingng mechanism, Ssortingng value) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 570 at OpenQA.Selenium.Remote.RemoteWebElement.FindElementByXPath(Ssortingng 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 

Si je modifie le test pour utiliser un ChromeDriver, le test réussit. Il me semble que cela signifie qu’il s’agit d’un problème lié à InternetExplorerDriver ou au navigateur Internet Explorer lui-même. Est-ce que quelqu’un sait quoi et s’il y a quelque chose que je peux faire pour contourner ce problème (le site sera utilisé dans IE par les utilisateurs finaux, donc changer de navigateur n’est pas possible, malheureusement)?


EDIT: La Thread.Sleep() actuelle que j’utilise consiste à mettre un Thread.Sleep() après la sélection de la liste. cela fonctionne mais n’est évidemment pas une solution idéale.

Ci-dessous, le schéma que j’ai fini par mettre en place

Après chaque item*.Select() j’ai mis en place une attente:

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

est un moyen de déterminer que la sélection d’élément est terminée (par exemple, en vérifiant qu’un autre contrôle de la page a été mis à jour, par exemple:

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

MyCustomWebDriverWait est une classe qui implémente IWait et est presque identique à la classe WebDriverWait . Elle attrape à la fois StaleElementReferenceException et NotFoundException (ce qui signifie changer le type de lastException de NotFoundException en WebDriverException .

Vous pouvez lire comment Daniel Wagner-Hall m’a indiqué dans cette direction à propos du groupe google des utilisateurs de Selenium ici .

L’élément de liste peut être en train de changer dans le DOM à cause de l’autopostback. Essayez de redéfinir l’élément de liste chaque fois que vous sélectionnez une option. Par exemple

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

J’ai trouvé qu’il était driver.refresh() appeler driver.refresh() après avoir driver.refresh() la page indiquant que cela fonctionnait bien, mon code est le suivant:

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