113 votes

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

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")); "

car il faut quelques secondes à mes applications pour charger l'interface utilisateur. J'ai donc mis 2 secondes implicitwait. mais je suis incapable de localiser l'élément textbox

Puis j'ajoute Thread.sleep(2000);

Maintenant cela fonctionne bien. Lequel est un meilleur moyen?

133voto

eugene.polschikov Points 3283

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

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

La notion d'implicite d'attente 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 fonction renvoie votre trouvées sur le web de l'élément. À partir de la documentation sur fluentWait: Une mise en œuvre de l'Attente de l'interface qui peut avoir son délai d'attente et l'interrogation sur l'intervalle configuré à la volée. Chaque FluentWait instance définit la quantité maximale de temps à attendre pour un état, ainsi que la fréquence avec laquelle vérifier la condition. En outre, l'utilisateur peut configurer l'attendre à ignorer certains types d'exceptions en attendant, comme NoSuchElementExceptions lors de la recherche d'un élément dans la page. Détails vous pouvez obtenir ici

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

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

Cette approche, à mon humble avis mieux que vous ne savez pas exactement combien de temps à attendre et, dans l'intervalle d'interrogation vous pouvez définir arbitraire timevalue de l'élément dont la présence sera vérifiée par le biais de . Ce qui concerne.

17voto

fornix Points 61

Si vous utilisez webdriverJs (node.js),

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

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

17voto

Jeff Vincent Points 61

Ce fil est un peu plus âgés, mais pensé que je poste ce que j'ai actuellement n' (travaux en cours).

Même si je suis encore de frapper les situations où le système est sous une charge lourde et quand je clique sur un bouton de soumission (par exemple, connexion.jsp), les trois conditions (voir ci-dessous) rendement true , mais la page suivante (p. ex., à la maison.jsp) n'a pas commencé à charger encore.

C'est un générique attendre méthode 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 les différents réutilisables ExpectedConditions (trois sont ci-dessous). Dans cet exemple, les trois conditions prévues comprennent document.readyState = "complet", pas de "wait_dialog", et non 'spinners' (éléments indiquant asynchrone de données est en cours de demande).

Seul le premier peut être générique appliqué à 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 peut utiliser l'une ou de la totalité d'entre eux:

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

Il y a aussi des prédéfinis ExpectedConditions dans la classe suivante: org.openqa.le sélénium.de soutien.l'interface utilisateur.ExpectedConditions

11voto

Valentin Points 2241

À l'aide de Thread.sleep(2000); est un inconditionnel de l'attendre. Si votre test de charge plus rapidement que vous aurez encore à attendre. Donc, en principe, à l'aide de implicitlyWait est la meilleure solution.

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

3voto

simno Points 31

J'aime utiliser des conditions personnalisées. 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 liste de retours - vide ou pas, il vous suffit de vérifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X