J'ai démarré un projet Selenium en C #. Si vous essayez d’attendre que la page se termine, puis passez à l’action suivante.
Mon code ressemble à ceci:
loginPage.GoToLoginPage();
loginPage.LoginAs(TestCase.Username, TestCase.Password);
loginPage.SelectRole(TestCase.Orgunit);
loginPage.AcceptRole();
à l'intérieur de loginPage.SelectRole (TestCase.Orgunit):
RoleHierachyLabel = CommonsBasePage.Driver.FindElement(By.XPath("//span[contains(text(), " + role + ")]"));
RoleHierachyLabel.Click();
RoleLoginButton.Click();
Je recherche l'élément RoleHierachyLabel. J'ai essayé d'utiliser plusieurs méthodes pour attendre que la page soit chargée ou rechercher une propriété d'élément permettant un certain délai d'expiration:
1. _browserInstance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
2. public static bool WaitUntilElementIsPresent(RemoteWebDriver driver, By by, int timeout = 5)
{
for (var i = 0; i < timeout; i++)
{
if (driver.ElementExists(by)) return true;
}
return false;
}
Comment aborderiez-vous cet obstacle?
J'ai cherché des alternatives et j'ai opté pour les versions suivantes. Tous utilisent l'attente explicite avec un délai d'expiration défini et sont basés sur les propriétés de l'élément dans le premier cas et sur la stalness de l'élément dans le deuxième cas.
Premier choix vérifierait les propriétés de l'élément jusqu'à l'expiration du délai imparti. Je suis arrivé aux propriétés suivantes qui confirment sa disponibilité sur la page:
Existence - Espérance de vérification de la présence d'un élément dans le DOM d'une page. Cela ne signifie pas nécessairement que l'élément est visible.
//this will not wait for page to load
Assert.True(Driver.FindElement(By elementLocator).Enabled)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementExists(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementExists(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
Visibility - Attente de vérifier qu'un élément est présent sur le DOM d'une page et visible. La visibilité signifie que l'élément n'est pas seulement affiché mais qu'il a également une hauteur et une largeur supérieures à 0.
//this will not wait for page to load
Assert.True(Driver.FindElement(By elementLocator).Displayed)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementVisible(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementIsVisible(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found.");
throw;
}
}
Cliquable - Une attente de vérification d'un élément est visible et activée de sorte que vous puissiez cliquer dessus.
//this will not wait for page to load
//both properties need to be true in order for element to be clickable
Assert.True(Driver.FindElement(By elementLocator).Enabled)
Assert.True(Driver.FindElement(By elementLocator).Displayed)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementClickable(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementToBeClickable(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
Deuxième choix s'applique lorsque l'objet déclencheur, par exemple un élément de menu, n'est plus attaché au DOM après avoir été cliqué. C'est généralement le cas lorsque l'action de clic sur l'élément déclenche une redirection vers une autre page. Dans ce cas, il est utile de cochez StalenessOf (element) où element est l'élément sur lequel vous avez cliqué pour déclencher la redirection vers la nouvelle page.
public static void ClickAndWaitForPageToLoad(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
var element = Driver.FindElement(elementLocator);
element.Click();
wait.Until(ExpectedConditions.StalenessOf(element));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);
Voir aussi cette réponse
Je l'ai fait pour résoudre ce type de problème. C'est une combinaison de minuteries et de boucles qui recherchent un élément spécifique jusqu'à l'expiration du délai après un certain nombre de millisecondes.
private IWebElement FindElementById(string id, int timeout = 1000)
{
IWebElement element = null;
var s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
{
try
{
element = _driver.FindElementById(id);
break;
}
catch (NoSuchElementException)
{
}
}
s.Stop();
return element;
}
J'ai aussi fait un pour l'élément activé
private IWebElement ElementEnabled(IWebElement element, int timeout = 1000)
{
var s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
{
if (element.Enabled)
{
return element;
}
}
s.Stop();
return null;
}
Comme indiqué dans attendez le chargement de la page dans Selenium :
En général, avec Selenium 2.0, le pilote Web ne doit restituer le contrôle au code de l'appelant qu'une fois qu'il a déterminé que la page a été chargée . Si ce n'est pas le cas, vous pouvez appeler
waitforelemement
, qui passe ensuite à l'appel defindelement
jusqu'à ce qu'il soit trouvé ou expire (le délai peut être défini).
J'utilise habituellement une attente explicite pour cela, et attend jusqu'à ce qu'un élément soit visible, puis passez à l'action suivante. Cela devrait ressembler à ceci:
WebDriverWait waitForElement = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
waitForElement.Until(ExpectedConditions.ElementIsVisible(By.Id("yourIDHere")));
Plus sur les attentes explicites ici: Attentes explicites Selenium C # et ici WebDriver Explicit attend
En raison de sa simplicité, j'aime cette solution. En outre, il a l'avantage d'éviter les attentes excessives et d'éliminer les conjectures par rapport à ce que pourrait être la limite d'attente maximale:
public bool WaitToLoad(By by)
{
int i = 0;
while (i < 600)
{
i++;
Thread.Sleep(100); // sleep 100 ms
try
{
driver.FindElement(by);
break;
}
catch { }
}
if (i == 600) return false; // page load failed in 1 min
else return true;
}
Ce qui peut être modifié pour inclure également un "timer" si le temps de latence de chargement des pages de surveillance est nécessaire:
public int WaitToLoad(By by)
{
int i = 0;
while (i < 600)
{
i++;
Thread.Sleep(100); // sleep 100 ms
try
{
driver.FindElement(by);
break;
}
catch { }
}
return i; // page load latency in 1/10 secs
}