Selenium c# Webdriver: attendre Jusqu'à ce que L'élément soit présent

je veux m'assurer qu'un élément est présent avant que le webdriver ne commence à faire des choses.

j'essaie d'obtenir quelque chose comme ça pour fonctionner:

WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
wait.Until(By.Id("login"));

je me bats principalement comment configurer la fonction anynomous..

141
demandé sur JJS 2011-08-09 11:49:06

20 réponses

alternativement, vous pouvez utiliser l'attente implicite:

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

une attente implicite est de dire à WebDriver de sonder le DOM pour un certain quantité de temps à essayer de trouver un élément ou des éléments s'ils sont pas immédiatement disponibles. Le réglage par défaut est de 0. Une fois réglé, le l'attente implicite est définie pour la vie de l'instance de L'objet WebDriver.

129
répondu Mike Kwan 2017-06-01 03:34:27

L'utilisation de la solution fournie par Mike Kwan peut avoir un impact sur la performance globale des tests, puisque l'attente implicite sera utilisée dans tous les appels de FindElement. Plusieurs fois vous voudrez que le FindElement échoue immédiatement quand un élément n'est pas présent (vous testez une page mal formée, des éléments manquants, etc.). Avec l'attente implicite, ces opérations attendraient l'expiration de tout le délai avant de lancer l'exception. L'attente implicite par défaut est définie à 0 deuxième.

j'ai écrit une petite méthode d'extension à To IWebDriver qui ajoute un paramètre timeout (en secondes) à la méthode FindElement (). C'est assez explicite:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }
}

Je n'ai pas caché L'objet WebDriverWait car sa création est très bon marché, cette extension peut être utilisée simultanément pour différents objets WebDriver, et je ne fais des optimisations que lorsque c'est nécessaire.

L'Usage est simple:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost/mypage");
var btn = driver.FindElement(By.CssSelector("#login_button"));
btn.Click();
var employeeLabel = driver.FindElement(By.CssSelector("#VCC_VSL"), 10);
Assert.AreEqual("Employee", employeeLabel.Text);
driver.Close();
227
répondu Loudenvier 2015-07-09 08:27:58

vous pouvez également utiliser

ExpectedConditions.ElementExists

donc vous chercherez un élément de disponibilité comme ça

new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(ExpectedConditions.ElementExists((By.Id(login))));

Source

75
répondu Humble Coder 2013-02-28 18:12:11

voici une variante de la solution de @Loudenvier qui fonctionne aussi pour obtenir plusieurs éléments:

public static class WebDriverExtensions
{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }
        return driver.FindElement(by);
    }

    public static ReadOnlyCollection<IWebElement> FindElements(this IWebDriver driver, By by, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => (drv.FindElements(by).Count > 0) ? drv.FindElements(by) : null);
        }
        return driver.FindElements(by);
    }
}
27
répondu Rn222 2012-04-04 18:20:05

inspirée de la solution de Loudenvier, voici une méthode d'extension qui fonctionne pour tous les objets ISearchContext, pas seulement IWebDriver, qui est une spécialisation de l'ancien. Cette méthode supporte également l'attente jusqu'à ce que l'élément soit affiché.

static class WebDriverExtensions
{
    /// <summary>
    /// Find an element, waiting until a timeout is reached if necessary.
    /// </summary>
    /// <param name="context">The search context.</param>
    /// <param name="by">Method to find elements.</param>
    /// <param name="timeout">How many seconds to wait.</param>
    /// <param name="displayed">Require the element to be displayed?</param>
    /// <returns>The found element.</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeout, bool displayed=false)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        wait.Timeout = TimeSpan.FromSeconds(timeout);
        wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
        return wait.Until(ctx => {
            var elem = ctx.FindElement(by);
            if (displayed && !elem.Displayed)
                return null;

            return elem;
        });
    }
}

exemple d'usage:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
var btn = main.FindElement(By.Id("button"));
btn.Click();
var dialog = main.FindElement(By.Id("dialog"), 5, displayed: true);
Assert.AreEqual("My Dialog", dialog.Text);
driver.Close();
14
répondu aknuds1 2012-11-08 16:05:05

J'ai confondu n'importe quelle fonction avec prédicate. Heres une petite aide de la méthode:

   WebDriverWait wait;
    private void waitForById(string id) 
    {
        if (wait == null)            
            wait = new WebDriverWait(driver, new TimeSpan(0,0,5));

        //wait.Until(driver);
        wait.Until(d => d.FindElement(By.Id(id)));
    }
9
répondu AyKarsi 2011-08-09 07:59:04

Vous pouvez trouver quelque chose comme ça en C# .

C'est ce que j'ai utilisé dans JUnit-sélénium

WebDriverWait wait = new WebDriverWait(driver, 100);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));

Faire importer des paquets

3
répondu Aditi 2014-08-04 14:15:34

la commande clickAndWait ne se convertit pas lorsque vous choisissez le format Webdriver dans L'IDE de sélénium. Voici la solution de contournement. Ajoutez la ligne d'attente ci-dessous. De façon réaliste, le problème était le clic ou l'événement qui s'est produit avant celui-ci--ligne 1 dans mon code C#. Mais vraiment, assurez-vous juste que vous avez un WaitForElement avant toute action où vous faites référence à un objet "By".

code HTML:

<a href="http://www.google.com">xxxxx</a>

C# / Code NUnit:

driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();
2
répondu MacGyver 2012-01-17 20:29:41

Python:

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By

driver.find_element_by_id('someId').click()

WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, 'someAnotherId'))

de EC vous pouvez choisir d'autres conditions aussi bien essayez ceci: http://selenium-python.readthedocs.org/api.html#module-selenium.webdriver.support.expected_conditions

2
répondu Md. Nazmul Haque Sarker 2014-04-16 06:33:56
//wait up to 5 seconds with no minimum for a UI element to be found
WebDriverWait wait = new WebDriverWait(_pagedriver, TimeSpan.FromSeconds(5));
IWebElement title = wait.Until<IWebElement>((d) =>
{
    return d.FindElement(By.ClassName("MainContentHeader"));
});
2
répondu Brian121212 2017-06-05 12:33:05

Attente Explicite

public static  WebDriverWait wait = new WebDriverWait(driver, 60);

exemple:

wait.until(ExpectedConditions.visibilityOfElementLocated(UiprofileCre.UiaddChangeUserLink));
1
répondu Pavan T 2016-02-17 10:42:50

essayez ce code:

 New WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(Function(d) d.FindElement(By.Id("controlName")).Displayed)
1
répondu Ammar Ben Hadj Amor 2017-09-17 18:43:06

Vous ne voulez pas attendre trop longtemps avant de l'élément change. Dans ce code, le webdriver attend jusqu'à 2 secondes avant de continuer.


WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromMilliseconds(2000));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("html-name")));

1
répondu user3607478 2018-08-15 21:23:44

puisque je sépare les définitions des éléments de page et les scénarios de test de page utilisant L'Ibebelement déjà trouvé pour la visibilité pourrait être fait comme ceci:

public static void WaitForElementToBecomeVisibleWithinTimeout(IWebDriver driver, IWebElement element, int timeout)
{
    new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until(ElementIsVisible(element));
}

private static Func<IWebDriver, bool> ElementIsVisible(IWebElement element)
{
    return driver => {
        try
        {
            return element.Displayed;              
        }
        catch(Exception)
        {
            // If element is null, stale or if it cannot be located
            return false;
        }
    };
}
1
répondu Angel D 2018-09-14 17:07:23

je vois plusieurs solutions déjà posté que le travail grand! Cependant, juste au cas où quelqu'un aurait besoin d'autre chose, j'ai pensé poster deux solutions que j'ai personnellement utilisées dans le sélénium C# pour tester si un élément est présent! Espérons que cela aide, cheers!

public static class IsPresent
{
    public static bool isPresent(this IWebDriver driver, By bylocator)
    {

        bool variable = false;
        try
        {
            IWebElement element = driver.FindElement(bylocator);
            variable = element != null;
        }
       catch (NoSuchElementException){

       }
        return variable; 
    }

}

Voici la seconde

    public static class IsPresent2
{
    public static bool isPresent2(this IWebDriver driver, By bylocator)
    {
        bool variable = true; 
        try
        {
            IWebElement element = driver.FindElement(bylocator);

        }
        catch (NoSuchElementException)
        {
            variable = false; 
        }
        return variable; 
    }

}
0
répondu newITguy 2012-09-27 15:08:29
public bool doesWebElementExist(string linkexist)
{
     try
     {
        driver.FindElement(By.XPath(linkexist));
        return true;
     }
     catch (NoSuchElementException e)
     {
        return false;
     }
}
0
répondu Madhu 2017-06-05 13:30:26

utilise Rn222 et Aknuds1 pour utiliser un ISearchContext qui renvoie soit un seul élément, soit une liste. Et un nombre minimum d'éléments peuvent être spécifiés:

public static class SearchContextExtensions
{
    /// <summary>
    ///     Method that finds an element based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeOutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns> The first element found that matches the condition specified</returns>
    public static IWebElement FindElement(this ISearchContext context, By by, uint timeOutInSeconds)
    {
        if (timeOutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeOutInSeconds);
            return wait.Until<IWebElement>(ctx => ctx.FindElement(by));
        }
        return context.FindElement(by);
    }
    /// <summary>
    ///     Method that finds a list of elements based on the search parameters within a specified timeout.
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds)
    {

        if (timeoutInSeconds > 0)
        {
            var wait = new DefaultWait<ISearchContext>(context);
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
            return wait.Until<IReadOnlyCollection<IWebElement>>(ctx => ctx.FindElements(by));
        }
        return context.FindElements(by);
    }
    /// <summary>
    ///     Method that finds a list of elements with the minimum amount specified based on the search parameters within a specified timeout.<br/>
    /// </summary>
    /// <param name="context">The context where this is searched. Required for extension methods</param>
    /// <param name="by">The search parameters that are used to identify the element</param>
    /// <param name="timeoutInSeconds">The time that the tool should wait before throwing an exception</param>
    /// <param name="minNumberOfElements">
    ///     The minimum number of elements that should meet the criteria before returning the list <para/>
    ///     If this number is not met, an exception will be thrown and no elements will be returned
    ///     even if some did meet the criteria
    /// </param>
    /// <returns>A list of all the web elements that match the condition specified</returns>
    public static IReadOnlyCollection<IWebElement> FindElements(this ISearchContext context, By by, uint timeoutInSeconds, int minNumberOfElements)
    {
        var wait = new DefaultWait<ISearchContext>(context);
        if (timeoutInSeconds > 0)
        {
            wait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
        }

        // Wait until the current context found the minimum number of elements. If not found after timeout, an exception is thrown
        wait.Until<bool>(ctx => ctx.FindElements(by).Count >= minNumberOfElements);

        //If the elements were successfuly found, just return the list
        return context.FindElements(by);
    }

}

exemple d'usage:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost");
var main = driver.FindElement(By.Id("main"));
// It can be now used to wait when using elements to search
var btn = main.FindElement(By.Id("button"),10);
btn.Click();
//This will wait up to 10 seconds until a button is found
var button = driver.FindElement(By.TagName("button"),10)
//This will wait up to 10 seconds until a button is found, and return all the buttons found
var buttonList = driver.FindElements(By.TagName("button"),10)
//This will wait for 10 seconds until we find at least 5 buttons
var buttonsMin= driver.FindElements(By.TagName("button"), 10, 5);
driver.Close();
0
répondu havan 2018-02-26 11:03:40

cherchait comment attendre dans le sélénium pour condition, atterri dans ce fil et voici ce que j'utilise maintenant:

    WebDriverWait wait = new WebDriverWait(m_driver, TimeSpan.FromSeconds(10));
    wait.Until(d => ReadCell(row, col) != "");

ReadCell(row, col) != "" peut être n'importe quelle condition. Comme ceci parce que:

  • c'est moi
  • permet inline
-1
répondu Michal Stefanow 2013-02-15 09:39:50
 new WebDriverWait(driver, TimeSpan.FromSeconds(10)).
   Until(ExpectedConditions.PresenceOfAllElementsLocatedBy((By.Id("toast-container"))));
-1
répondu david 2016-08-18 21:29:59

première réponse est bonne, mon problème était que exceptions non réglées ne fermait pas correctement le pilote web et il a gardé la même valeur que j'avais utilisé qui était de 1 seconde.

si vous avez le même problème

restart you visual studio et de s'assurer que all the exceptions are handled correctement.

-1
répondu Pete Kozak 2016-10-09 02:58:05