Per aggiungere alla risposta di @ jarib, ho creato diversi metodi di estensione che aiutano a eliminare le condizioni di gara.
Ecco la mia configurazione:
Ho una classe chiamata "Driver.cs". Contiene una classe statica piena di metodi di estensione per il driver e altre utili funzioni statiche.
Per gli elementi che di solito ho bisogno di recuperare, creo un metodo di estensione come il seguente:
public static IWebElement SpecificElementToGet(this IWebDriver driver) {
return driver.FindElement(By.SomeSelector("SelectorText"));
}
Ciò consente di recuperare quell'elemento da qualsiasi classe di test con il codice:
driver.SpecificElementToGet();
Ora, se questo si traduce in a StaleElementReferenceException
, ho il seguente metodo statico nella mia classe di driver:
public static void WaitForDisplayed(Func<IWebElement> getWebElement, int timeOut)
{
for (int second = 0; ; second++)
{
if (second >= timeOut) Assert.Fail("timeout");
try
{
if (getWebElement().Displayed) break;
}
catch (Exception)
{ }
Thread.Sleep(1000);
}
}
Il primo parametro di questa funzione è qualsiasi funzione che restituisce un oggetto IWebElement. Il secondo parametro è un timeout in secondi (il codice per il timeout è stato copiato dall'IDE Selenium per FireFox). Il codice può essere utilizzato per evitare l'eccezione dell'elemento non aggiornato nel modo seguente:
MyTestDriver.WaitForDisplayed(driver.SpecificElementToGet,5);
Il codice precedente chiamerà driver.SpecificElementToGet().Displayed
fino a quando driver.SpecificElementToGet()
non genera eccezioni e .Displayed
valutatrue
non passerà 5 secondi. Dopo 5 secondi, il test fallirà.
D'altro canto, per attendere che un elemento non sia presente, è possibile utilizzare la seguente funzione allo stesso modo:
public static void WaitForNotPresent(Func<IWebElement> getWebElement, int timeOut) {
for (int second = 0;; second++) {
if (second >= timeOut) Assert.Fail("timeout");
try
{
if (!getWebElement().Displayed) break;
}
catch (ElementNotVisibleException) { break; }
catch (NoSuchElementException) { break; }
catch (StaleElementReferenceException) { break; }
catch (Exception)
{ }
Thread.Sleep(1000);
}
}