web-dev-qa-db-fra.com

Quand utiliser l'attente explicite ou l'attente implicite dans Selenium Webdriver?

J'utilise:

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

Mais il échoue toujours pour l'élément ci-dessous 

    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 prendre soin d'attendre jusqu'à ce qu'un élément soit trouvé? Serait-il également préférable d'utiliser l'attente explicite au lieu du code que j'ai ajouté et qui contient Thread.sleep()?

37
SUM

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


Voici un rapide aperçu des différences entre attente explicite et implicite:

Attente explicite:

  • comportement documenté et défini.
  • s'exécute dans la partie locale de Selenium (dans la langue de votre code).
  • fonctionne à toutes les conditions auxquelles vous pouvez penser.
  • renvoie une erreur de réussite ou de dépassement de délai.
  • peut définir l'absence d'élément comme condition de réussite.
  • peut personnaliser le délai entre les tentatives et les exceptions à ignorer.

Attente implicite:

  • comportement non documenté et pratiquement non défini.
  • fonctionne dans la partie distante de Selenium (la partie contrôlant le navigateur).
  • ne fonctionne que sur les méthodes find élément (s).
  • renvoie soit l'élément trouvé, soit (après expiration du délai) non trouvé.
  • si la vérification de l'absence d'élément doit toujours attendre le délai d'attente.
  • ne peut pas être personnalisé autre que le délai d'expiration global.

Voyons la différence entre attente explicite et attente implicite dans le code source actuel de Selenium. J'ai copié le code de la liaison python de Selenium car python est "facile à lire".

Le code de WebDriverWait.until() (attente explicite):

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)

En langage humain, l'attente explicite attend une méthode qui renvoie une valeur True si elle aboutit. Il exécute ensuite à 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 réelle, l'attente explicite renverra cette valeur. Si le délai est écoulé, une exception de délai d'attente est déclenchée.

Comparez au code de WebDriver.implicitly_wait() (commentaires supprimés par souci de brièveté):

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

self.execute() est WebDriver.execute() qui appelle RemoteConnection.execute() qui, à mon avis, constitue un RPC situé du côté éloigné de Selenium.

En langage humain: l'attente implicite envoie un message au "côté distant" du WebDriver Selenium. Le côté distant du sélecteur de sites Web Selenium est la partie de Selenium qui contrôle actuellement le navigateur. Que fait le côté distant avec le message? "Ça dépend". Cela dépend du système d'exploitation, du navigateur et de la version de Selenium. Autant que je sache, rien ne garantit le comportement réel d'une implémentation spécifique.

Les implémentations possibles sont:

  • essayez à plusieurs reprises de trouver l'élément jusqu'à l'expiration du délai. retourne dès que l'élément est trouvé.
  • essayez de trouver l'élément. attendez le délai d'attente. réessayer.
  • attendez le délai d'attente. essayez de trouver l'élément.

Notez que l'attente implicite ne prend effet que sur les méthodes de recherche d'élément (s).

Je n'ai pas cherché le code source des côtés distants de Selenium. Les informations sont recueillies en lisant les commentaires dans les rapports de bugs sur l’attente implicite et explicite dans Selenium :

Ma conclusion: l'attente implicite est mauvaise. Les capacités sont limitées. Le comportement est non documenté et dépend de la mise en œuvre.

L'attente explicite peut faire tout ce qui est implicite, voire plus. Le seul inconvénient de l'attente explicite est un peu plus important à cause des appels multiples de procédures distantes. En outre, l'attente explicite est un peu plus détaillée. Mais cette verbosité rend le code explicite. Et explicite vaut mieux qu'implicite. Droite?


Lectures complémentaires:

80
lesmana

Attente implicite - C'est paramètre global applicable pour tous les éléments. Si l'élément apparaît avant l'heure spécifiée, le script commencera à s'exécuter, sinon le script lancera NoSuchElementException. Meilleure façon d'utiliser la méthode d'installation. N'affectez que By.findelement().

Thread.sleep() - Il sera temps de dormir pour le script, pas le bon moyen à utiliser dans le script car il est en veille sans condition. Et si 2 secondes ne suffisaient pas dans 5% des cas?

Attente explicite : Attendre spécifier contenir/attribut changer. Plus utilisé lorsque l’application donneAJAXun appel au système et obtient des données dynamiques et un rendu sur l’interface utilisateur. Dans ce cas, WebDriverWait convient.

4
Anand Somani

Avez-vous essayé fluentWait? Une implémentation de l'interface Wait dont le délai d'attente et l'interrogation peut être configuré à la volée . Chaque instance de FluentWait définit le délai d'attente maximal d'une condition, ainsi que la fréquence. avec lequel vérifier l'état. De plus, l'utilisateur peut configurer l'attente pour ignorer des types d'exceptions spécifiques pendant l'attente, tels que NoSuchElementExceptions lors de la recherche d'un élément sur la page.

voir ce lien description d'attente courante

En particulier, j'ai utilisé l'attente courante de cette manière:

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 avez remarqué, les éléments d’attente trouvés sont renvoyés. Donc, vous passez simplement le localisateur avec Par type et vous pouvez ensuite effectuer toutes les actions sur l'élément Web trouvé.

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

J'espère que cela vous aide)

4
eugene.polschikov

Avez-vous essayé d'utiliser ' WebDriverWait '? J'imagine 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 :)

À ma connaissance, cela fera à peu près ce que votre code actuel est. Il essaiera constamment la méthode (en ignorant les exceptions non trouvées) jusqu'à ce que le délai d'expiration de la période écoulée soit atteint et qu'un troisième paramètre puisse être entré pour spécifier le sommeil en millisecondes . Désolé si c'est ce que vous attend implicitement aussi!

Edit: J’ai lu un peu aujourd’hui et je comprends mieux votre question et je réalise que cela correspond exactement à ce que votre réglage d’attente implicite devrait faire. Je le laisserai ici au cas où le code lui-même pourrait aider quelqu'un d'autre.

2
Nashibukasan

ImplicitWait:

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

Déclarer l'attente implicite en Java - Selenium:

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

Attente explicite:

  1. Attente dynamique
  2. Attente conditionnelle.
  3. Non applicable tout au long du programme 

Déclaration de l'attente explicite dans Java Selenium.

WebDriverWait wait=new WebDriverWait(driver, 20); wait.until(somecondition);
1
Kiran Sk

Les attentes implicites sont utilisées pour fournir un temps d'attente (par exemple, 30 secondes) entre chaque étape de test consécutive sur l'ensemble du script ou du programme de test. La prochaine étape n'est exécutée qu'après l'exécution de l'étape précédente (ou quel que soit le temps imparti)

Syntaxe:  

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

Les attentes explicites sont utilisées pour arrêter l'exécution jusqu'à ce qu'une condition particulière soit remplie ou que le temps maximum défini soit écoulé. Une attente implicite s’est appliquée entre chaque étape de test consécutive sur l’ensemble du script ou des programmes de test, tandis que les attentes explicites ne sont appliquées que pour une instance particulière.

Syntaxe:  

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver,30);
0
iamsankalp89