Comment puis-je demander au Selenium-WebDriver d'attendre quelques secondes en Java?


Je travaille sur un Java Selenium-WebDriver. J'ai ajouté

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

Et

WebElement textbox = driver.findElement(By.id("textbox"));

Parce que mes Applications prennent quelques secondes pour charger l'interface utilisateur. J'ai donc mis 2 secondes implicitwait. mais j'ai eu impossible de localiser l'élément textbox

Puis j'ajoute Thread.sleep(2000);

Maintenant, cela fonctionne bien. Lequel est le meilleur moyen?

Author: kenorb, 2012-10-12

15 answers

Eh bien, il existe deux types d'attente: l'attente explicite et l'attente implicite. L'idée de l'attente explicite est

WebDriverWait.until(condition-that-finds-the-element);

Le concept d'attente implicite est

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

, Vous pouvez obtenir de différence dans les détails ici.

Dans de telles situations, je préfère utiliser explicite attendre (fluentWait, en particulier):

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;
};

fluentWait la fonction renvoie votre élément web trouvé. À partir de la documentation sur fluentWait: Une implémentation de l'interface d'attente qui peut avoir son délai d'attente et son intervalle d'interrogation configuré à la volée. Chaque instance FluentWait définit la durée maximale d'attente d'une condition, ainsi que la fréquence à laquelle vérifier la condition. En outre, l'utilisateur peut configurer l'attente pour ignorer des types spécifiques d'exceptions pendant l'attente, tels que NoSuchElementExceptions lors de la recherche d'un élément sur la page. Les détails que vous pouvez obtenir ici

L'Utilisation de fluentWait, dans votre cas, être la suivante:

WebElement textbox = fluentWait(By.id("textbox"));

Cette approche IMHO mieux que vous le faites je ne sais pas exactement combien de temps attendre et dans l'intervalle d'interrogation, vous pouvez définir timevalue arbitraire par lequel la présence de l'élément sera vérifiée . Égard.

 123
Author: eugene.polschikov, 2015-04-13 11:29:16

Ce fil est un peu plus ancien, mais je pensais poster ce que je fais actuellement (travail en cours).

Bien que je rencontre toujours des situations où le système est sous forte charge et lorsque je clique sur un bouton de soumission (par exemple, connexion.jsp), les trois conditions (voir ci-dessous) renvoient true mais la page suivante (par exemple, home.jsp) n'a pas encore commencé le chargement.

Il s'agit d'une méthode d'attente générique qui prend une liste de ExpectedConditions.

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

J'ai défini diverses conditions d'attente réutilisables (trois sont ci-dessous). Dans cet exemple, les trois conditions attendues incluent document.readyState = 'complete', pas de" wait_dialog "présent et pas de "spinners" (éléments indiquant que des données asynchrones sont demandées).

Seul le premier peut être appliqué de manière générique à toutes les pages Web.

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

Selon la page, je peux utiliser un ou tous:

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

Il existe également des conditions d'attente prédéfinies dans la classe suivante: org.openqa.nium.soutien.interface.Conditions attendues

 16
Author: Jeff Vincent, 2014-11-08 00:39:05

Si vous utilisez webdriverJs (node.js),

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

Le code ci-dessus fait attendre le navigateur pendant 5 secondes après avoir cliqué sur le bouton.

 13
Author: Anup, 2013-09-17 19:46:48

L'utilisation de Thread.sleep(2000); est une attente inconditionnelle. Si votre test se charge plus rapidement, vous devrez toujours attendre. Donc, en principe, utiliser implicitlyWait est la meilleure solution.

Cependant, je ne vois pas pourquoi implicitlyWait ne fonctionne pas dans votre cas. Avez-vous mesuré si le findElement prend réellement deux secondes avant de lancer une exception. Si oui, pouvez-vous essayer d'utiliser l'attente conditionnelle de WebDriver comme décrit dans cette réponse?

 10
Author: Valentin, 2017-05-23 12:03:02

J'aime utiliser des conditions. Voici du code en Python:

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

Chaque fois que vous devez attendre, vous pouvez le faire explicitement en vérifiant l'existence d'un certain élément (cet élément peut varier d'une page à l'autre). find_elements_by_id renvoie la liste - vide ou non, il vous suffit de vérifier.

 3
Author: simno, 2014-02-20 11:20:20

Le clic semble bloquer? - voici une autre façon d'attendre si vous utilisez WebDriverJS:

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

Le code ci-dessus attend après avoir cliqué sur le bouton que la page suivante se charge, puis saisit la source de la page suivante.

 2
Author: Dion, 2014-02-28 02:03:57

Implicitement attendre et Thread.sommeil Les deux sont utilisés uniquement pour la synchronisation..mais la différence est que nous pouvons utiliser implicitement attendre tout le programme mais Thread.le sommeil ne fonctionne que pour ce code unique..Ici, ma suggestion est d'utiliser Implicitement attendre une fois dans le programme lorsque chaque fois que votre page Web sera actualisée signifie utiliser Thread.dors là time..it sera beaucoup mieux:)

Voici mon code:

package beckyOwnProjects;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}
 1
Author: Beckham Vinoth, 2015-12-19 12:48:34

Utiliser des actions -

L'API orientée utilisateur pour émuler des gestes utilisateur complexes.

Voir les Actions#pause méthode.

 1
Author: Dzmitry Sankouski, 2019-12-24 07:55:57

Parfois, l'attente implicite semble être remplacée et le temps d'attente est raccourci. [@Eugene.polschikov] avait une bonne documentation sur les pourquoi. J'ai trouvé dans mes tests et mon codage avec Selenium 2 que les attentes implicites sont bonnes mais parfois vous devez attendre explicitement.

Il est préférable d'éviter d'appeler directement un thread pour dormir, mais parfois il n'y a pas un bon moyen de le contourner. Cependant, il existe d'autres options d'attente fournies par Selenium qui aident. waitForPageToLoad et waitForFrameToLoad se sont révélés particulièrement utiles.

 0
Author: BadgerAndK, 2013-02-05 19:37:39

Parfois, l'attente implicite échoue, disant qu'un élément existe mais qu'il ne l'est pas vraiment.

La solution consiste à éviter d'utiliser le pilote.findElement et de le remplacer par une méthode personnalisée qui utilise implicitement une Attente explicite. Par exemple:

import org.openqa.selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

Il existe d'autres raisons d'éviter l'attente implicite que les échecs sporadiques et occasionnels (voir ce lien ).

Vous pouvez utiliser cette méthode "element" de la même manière que driver.findÉlément. Pour Exemple:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

Si vous voulez vraiment attendre quelques secondes pour le dépannage ou une autre occasion rare, vous pouvez créer une méthode de pause similaire à ce que propose selenium ID:

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
 0
Author: JohnP2, 2017-07-11 18:06:03

Réponse : attendez quelques secondes avant que la visibilité des éléments à l'aide de Selenium WebDriver passe par les méthodes ci-dessous.

ImplicitlyWait () : L'instance WebDriver attend le chargement complet de la page. Vous utilisez muse 30 à 60 secondes pour attendre le chargement de la page complète.

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

ExplicitlyWait WebDriverWait () : L'instance WebDriver attend le chargement complet de la page.

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

Remarque : Veuillez utiliser ExplicitlyWait WebDriverWait() pour gérer un élément Web particulier.

 0
Author: sandeep shewale, 2018-04-05 08:36:22

Je préfère que le code suivant attende 2 secondes.

for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
   Thread.sleep(1000);
}
 -1
Author: Gangadhar, 2013-11-26 08:44:13

Attente implicite: Pendant l'attente implicite si le pilote Web ne peut pas le trouver immédiatement en raison de sa disponibilité, le pilote Web attendra l'heure mentionnée et il n'essaiera pas de retrouver l'élément pendant la période spécifiée. Une fois le temps spécifié terminé, il essaiera de rechercher à nouveau l'élément la dernière fois avant de lancer une exception. Le paramètre par défaut est zéro. Une fois que nous avons défini une heure, le pilote Web attend la période de l'instance d'objet WebDriver.

Explicite Attendez: Il peut y avoir un exemple où un élément particulier prend plus d'une minute à charger. Dans ce cas, vous n'aimez certainement pas définir un temps énorme pour attendre implicitement, comme si vous le faisiez, votre navigateur attendra le même temps pour chaque élément. Pour éviter cette situation, vous pouvez simplement mettre une fois sur l'élément requis uniquement. En suivant cela, le temps d'attente implicite de votre navigateur serait court pour chaque élément et il serait important pour un élément spécifique.

 -1
Author: Abhishek Singh, 2015-12-27 07:49:03
Thread.sleep(1000);

Est le pire: étant une attente statique, cela ralentira le script de test.

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

C'est une attente dynamique

  • il est valide jusqu'à l'existence du webdriver ou a une portée jusqu'à la durée de vie du pilote
  • nous pouvons attendre implicitement aussi.

Enfin, ce que je suggère est

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);

Avec quelques conditions prédéfinies:

isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
  • C'est aussi une attente dynamique
  • dans ce cas, l'attente ne sera que de quelques secondes
  • , nous avons à l'utilisation explicite d'attente pour un élément web particulier sur lequel nous voulons utiliser.
 -1
Author: Shobhit, 2018-02-16 21:59:38
Thread.Sleep(5000);

Cela m'a aidé mais l'exception InterruptedException doit être prise en charge. Donc, mieux l'entourer avec try and catch:

try {
    Thread.Sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

OU

Ajouter jette déclaration:

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

, je préfère la seconde, car on peut alors utiliser sleep() autant de fois qu'il le veut et éviter la répétition de try et catch bloc à chaque fois où sleep() a été utilisé.

 -4
Author: Prasad Hajare, 2019-02-08 15:30:34