Quand utiliser explicit wait vs implicit wait dans Selenium Webdriver?

j'utilise:

driver.manage().timeouts().implicitlyWait(180, TimeUnit.SECONDS);

mais il échoue toujours pour l'élément

    driver.findElement(By.id("name")).clear();
    driver.findElement(By.id("name")).sendKeys("Create_title_01");

j'ai ajouté le code d'attente:

for (int second = 0;; second++) {
        if (second >= 120) fail("timeout");
        try { if (isElementPresent(By.id("name"))) break; } catch (Exception e) {}
        Thread.sleep(1000);
    }

l'attente implicite ne devrait-elle pas s'occuper de l'attente jusqu'à ce qu'un élément soit trouvé? Serait-il également préférable que J'utilise Explicit wait au lieu du code que j'ai ajouté qui a Thread.sleep()?

35
demandé sur Darrel Holt 2012-05-02 00:50:33

6 réponses

TL; DR: toujours utiliser l'attente explicite. Oubliez que l'attente implicite existe.


Voici un rapide aperçu sur les différences entre l'explicite et l'implicite d'attente:

Explicite d'attente:

  • comportement documenté et défini.
  • s'exécute dans la partie locale de sélénium (dans la langue de votre code).
  • fonctionne dans toutes les conditions que vous pouvez imaginer.
  • renvoie succès ou temps mort erreur.
  • peut définir l'absence d'élément comme condition de succès.
  • peut personnaliser le délai entre les tentatives et les exceptions pour l'ignorer.

Implicite d'attente:

  • comportement non documenté et pratiquement non défini.
  • s'exécute dans la partie reculée de sélénium (la partie contrôle du navigateur).
  • ne fonctionne que sur les méthodes de find element(s).
  • renvoie l'un des éléments trouvés ou (après timeout) Non trouver.
  • si la vérification de l'absence de l'élément doit toujours attendre l'expiration du délai.
  • ne peut pas être personnalisé autre que global timeout.

voyons la différence entre l'attente explicite et l'attente implicite dans le code source réel du sélénium. J'ai copié le code à partir de la liaison python du sélénium parce que python est "facile à lire".

le code de WebDriverWait.until() (explicite d'attente):

def until(self, method, message=''):
    end_time = time.time() + self._timeout
    while(True):
        try:
            value = method(self._driver)
            if value:
                return value
        except self._ignored_exceptions:
            pass
        time.sleep(self._poll)
        if(time.time() > end_time):
            break
    raise TimeoutException(message)

Maintenant en langage humain: explicit wait attend une méthode qui renvoie une valeur truish si elle réussit. Il exécute alors à plusieurs reprises la méthode donnée avec un délai entre les deux. Les erreurs attendues de la méthode donnée sont supprimées. Si la méthode donnée renvoie une valeur truish, alors explicit wait retournera cette valeur. Si le temps s'écoule, une exception est soulevée.

comparez au code de WebDriver.implicitly_wait() (commentaires supprimés pour des raisons de concision):

def implicitly_wait(self, time_to_wait):
    self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000})

self.execute() est WebDriver.execute() quels appels RemoteConnection.execute() qui à son tour fait, pour autant que je puisse en juger, un RPC du côté éloigné du sélénium.

en langage humain: l'attente implicite envoie un message au "côté distant" du webdriver du sélénium. Le côté distant du driver selenium est la partie de selenium qui contrôle en fait le navigateur. Qu'est-ce que le côté distant fait avec le message? "Cela dépend". Cela dépend du système d'exploitation et du navigateur et sur la version du sélénium. Pour autant que je sache, il n'existe aucune garantie quant au comportement réel d'une mise en œuvre spécifique.

les implémentations possibles sont:

  • essayez à plusieurs reprises de trouver l'élément jusqu'à l'expiration du temps. de retour dès que l'élément est trouvé.
  • essayez de rechercher un élément. attendez jusqu'à ce que délai. réessayer.
  • attendez l'expiration du délai. essayez de rechercher un élément.

notez que l'attente implicite ne prend effet que sur l'élément find (s) méthode.

Je n'ai pas cherché le code source réel des côtés éloignés du sélénium. L'information est tirée de la lecture des commentaires dans le bug signale une attente implicite et explicite dans le sélénium:

ma conclusion: L'attente implicite est mauvaise. Les capacités sont limitées. Le comportement n'est pas documenté et dépend de la mise en œuvre.

L'attente explicite peut faire tout ce que l'attente implicite peut faire et plus encore. Le seul inconvénient de l'explicite wait est un peu plus overhead en raison de plusieurs appels de procédure à distance. Aussi l'attente explicite est un peu plus verbeuse. Mais cette verbosité rend le code explicite. Et explicite est mieux qu'implicite. Droit?


autres lectures:

70
répondu lesmana 2017-05-23 11:55:06

Implicite attendre -paramètre global applicable à tous les éléments et si l'élément apparaît avant l'heure spécifiée, le script commencera à exécuter sinon le script lancera NoSuchElementException. Meilleure façon d'utiliser dans la méthode de configuration. Seulement affecter By.findelement().

pas bon à utiliser en script car c'est du sommeil sans condition. Que faire si 2 secondes ne suffisent pas à 5% de la les cas?

Explicite attendre: Attendre pour spécifier contient/attribut à modifier. Plus utilisé lorsque l'application donne AJAX appeler au système et obtenir des données dynamiques et rendre sur L'UI. Dans ce cas WebDriverWait convient.

4
répondu Anand Somani 2016-02-10 19:38:52

voir ce lien couramment attendre description

en particulier j'ai utilisé fluent wait de cette façon:

public WebElement fluentWait(final By locator){
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class);

        WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                }
                }
);
                           return  foo;              }     ;

comme vous l'avez remarqué, "fluent wait returns" renvoie l'élément web trouvé. Ainsi, vous passez simplement le localisateur par type, puis vous pouvez effectuer toutes les actions sur l'élément web trouvé.

fluentWait(By.id("name")).clear();

j'Espère que ça vous aide)

3
répondu eugene.polschikov 2012-09-03 13:24:21

Avez-vous essayé d'utiliser ' WebDriverWait' ? J'imagine ce que vous voulez, c'est ceci:

WebDriverWait _wait = new WebDriverWait(driver, new TimeSpan(0, 0, 2)); //waits 2 secs max
_wait.Until(d => d.FindElement(By.Id("name")));
//do your business on the element here :)

ceci fera, à ma connaissance, ce qu'est votre code actuel. Il va constamment essayer la méthode (tout en ignorant les exceptions non trouvées) jusqu'à ce que le délai d'attente de l'intervalle passé dans le temps soit atteint et un troisième paramètre peut être entré pour spécifier le sommeil en millisecondes. Désolé si c'est ce que fait implicitlyWait aussi!

Edit: j'ai fait un peu de lecture aujourd'hui et comprenez mieux votre question et réalisez que cela fait exactement ce que votre réglage de l'attente implicite devrait faire. En remets ici au cas où le code lui-même peut aider quelqu'un d'autre.

2
répondu Nashibukasan 2012-05-02 01:23:28

ImplicitWait:

    1. Static Wait 
    2. UnConditional Wait. ( No Conditions were given)
    3. Applicable throughout the program

Déclarant le implicites attendre en java - le sélénium:

driver.manage().timeout().implicitWait(20, TimeUnit.Seconds());

Explicite D'Attente:

  1. Dynamique Attendre
  2. Conditionnel Attendre.
  3. Non applicable tout au long du programme

Déclarant explicitement Attendre en Java Sélénium.

WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition);
1
répondu Kiran Sk 2017-12-07 13:26:45

temps D'attente implicites sont utilisés pour fournir un temps d'attente (disons 30 secondes) entre chaque étape de test consécutive sur l'ensemble du script ou du programme de test. Prochaine étape n'est effectuée que lorsque les 30 Secondes (ou quel que soit le délai est écoulé) après l'exécution de l'étape précédente

Syntaxe:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

attente explicite sont utilisées pour interrompre l'exécution à la fois une condition particulière est remplie ou le temps maximum qui est défini, s'est écoulé. Une attente implicite s'est appliquée entre chaque étape de test consécutive dans l'ensemble du script de test ou des programmes, alors qu'une attente explicite est appliquée pour une instance particulière seulement.

Syntaxe:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver,30);
0
répondu iamsankalp89 2017-08-08 06:13:44