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 => );
Où
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();