web-dev-qa-db-fra.com

Quel est le meilleur moyen d'éviter NoSuchElementException in Selenium?

J'ai écrit quelques scénarios de test dans Selenium WebDriver à l'aide de Java et je les exécute sur une grille (concentrateur et nœuds multiples). J'ai remarqué que quelques cas de test échouaient à cause de NoSuchElementException. Quel est le moyen le plus efficace et le plus robuste d'éviter NoSuchElementException et de s'assurer que l'élément est toujours trouvé?

17
Parminder Singh

Vous ne pouvez jamais être sûr que cet élément sera trouvé, c'est en fait un but de test fonctionnel - pour vous dire si quelque chose a changé sur votre page. Mais une chose qui aide vraiment est d’attendre les éléments qui causent souvent NoSuchElementException comme

WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
25
Petr Mensik

Je suis complètement d'accord avec Petr Mensik ci-dessus. En ce qui concerne le sujet, vous ne pouvez jamais dire si un élément est présent .. Vous devez clairement comprendre pourquoi. D'après mon expérience, je dois dire que cela se produit pour les raisons suivantes:

  • 1) La page est toujours en cours de rendu et vous avez déjà terminé votre recherche d’élément Et n’obtenez aucune exception d’élément.
  • 2) La deuxième raison est que AJAX n’est pas encore revenu et que vous avez déjà Obtenir NoSuchElementException
  • 3) La troisième est la plus évidente: l'élément n'est vraiment pas sur la page

par conséquent, le moyen le plus robuste d'IMHO de gérer ces trois conditions à l'aide d'un seul appel de fonction consiste à utiliser fluentWait comme suggéré par Amith003.

donc le code soit le suivant:

laissez ur élément le localisateur:

String elLocXpath= "..blablabla";
WebElement myButton= fluentWait(By.xpath(elLocXpath));
myButton.click();

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

                .pollingEvery(5, TimeUnit.SECONDS)

        .ignoring(org.openqa.Selenium.NoSuchElementException.class);
        WebElement foo = wait.until(
                new Function<WebDriver, WebElement>() {
                    public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                    }
                }
        );
        return  foo;
    };

De même, si votre objectif est d'utiliser un code robuste fluentWait() avec un bloc try{} catch{}.

Aussi n'oubliez pas de

 public boolean isElementPresent(By selector)
   {

              return driver.findElements(selector).size()>0;
}

c'est aussi utile.

Donc, pour conclure tout ce qui est mentionné si vous voulez éviter une exception NoElement, gérez-la correctement, personne ne pouvant assurer la présence de l'élément sur la page.

J'espère que maintenant c'est plus clair pour vous. Cordialement

5
eugene.polschikov

vous pouvez aussi utiliser FluentWait,

Chaque instance FluentWait définit le délai maximal d’attente d’une condition, ainsi que la fréquence de vérification de la condition.

En outre, 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.

// Waiting 30 seconds for an element to be present on the page, checking
   // for its presence once every 5 seconds.
   Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
       .withTimeout(30, SECONDS)
       .pollingEvery(5, SECONDS)
       .ignoring(NoSuchElementException.class);

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

Cliquez ici pour plus d'informations

4
Amith
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));

elementToBeClickable attend Enable et Visible d'un élément 

1
Satish
public WebElement fluientWaitforElement(WebElement element, int timoutSec, int pollingSec) {

    FluentWait<WebDriver> fWait = new FluentWait<WebDriver>(driver).withTimeout(timoutSec, TimeUnit.SECONDS)
    .pollingEvery(pollingSec, TimeUnit.SECONDS)
    .ignoring(NoSuchElementException.class, TimeoutException.class);

    for (int i = 0; i < 2; i++) {
        try {
            //fWait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[@id='reportmanager-wrapper']/div[1]/div[2]/ul/li/span[3]/i[@data-original--title='We are processing through trillions of data events, this insight may take more than 15 minutes to complete.']")));
            fWait.until(ExpectedConditions.visibilityOf(element));
            fWait.until(ExpectedConditions.elementToBeClickable(element));
        } 
        catch (Exception e) {

            System.out.println("Element Not found trying again - " + element.toString().substring(70));
            e.printStackTrace();
        }
    }

    return element;
}
1
Ashwini

Nous pouvons appliquer les codes ci-dessous pour supprimer cette condition d'exception

  1. En appliquant WebDriverWait, l’objet webdriver attend une durée spécifique (en secondes) d’un élément pour sa visibilité.

          WebDriverWait wait = new WebDriverWait(driver, 10);       
           wait.until(ExpectedConditions.visibilityOf(link));
    
  2. Nous pouvons gérer NoSuchElementException via un bloc try-catch dans la méthode générique

     public boolean isElementPresent(By by) {
     boolean isPresent = true;
     try {
     driver.findElement(by);
     } catch (NoSuchElementException e) {
      isPresent = false;
     }
    return isPresent
    }
    

http://Selenium-code.blogspot.in/2017/08/Selenium-exception-nosuchelementexcepti.html

0
Ankit Vijay

J'utilise habituellement cette ligne dans la fonction principale

public static void main(String[] args) throws ParseException {
    driver= new ChromeDriver();
    driver.manage().window().maximize();
    **driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);**

J'espère que cela t'aides.

0
Chetu19