Attendre le chargement de la page dans le sélénium

Comment faire sélénium 2.0 attendez que la page se charge?

197
demandé sur Peter Mortensen 2011-05-03 14:59:15

30 réponses

vous pouvez aussi vérifier pageloaded en utilisant le code suivant

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));

 wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
119
répondu Imran 2012-07-06 12:23:21

Utilisation de la classe WebDriverWait

Voir aussi ici

vous pouvez Vous attendre à montrer certains de l'élément. quelque chose comme dans C#:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
83
répondu Artem 2017-09-26 05:52:15

si vous définissez l'attente implicite du pilote, puis appelez la méthode findElement sur un élément que vous prévoyez être sur la page chargée, le WebDriver Pollera pour cet élément jusqu'à ce qu'il trouve l'élément ou atteigne la valeur time out.

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

source: implicite-waits

31
répondu Sam 2014-10-22 05:20:30

en général, avec Selenium 2.0, le pilote web ne doit retourner le contrôle au code appelant qu'une fois qu'il a déterminé que la page a été chargée. Si ce n'est pas le cas , vous pouvez appeler waitforelemement , qui tourne autour de l'appel findelement jusqu'à ce qu'il soit trouvé ou times out (time out peut être défini).

30
répondu Paul Hadfield 2015-10-10 10:43:50

Ruby mise en œuvre:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}
21
répondu allenhwkim 2015-10-10 10:48:56

vous pouvez supprimer la ligne System.out . Il est ajouté à des fins de débogage.

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}
13
répondu QIKHAN 2015-10-10 10:59:03

vous pouvez également utiliser la classe: ExpectedConditions pour attendre explicitement qu'un élément apparaisse sur la page Web avant que vous ne puissiez prendre des mesures autres actions

vous pouvez utiliser la classe ExpectedConditions pour déterminer si un élément est visible:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

voir ExpectedConditions class Javadoc pour la liste de toutes les conditions que vous pouvez vérifier.

11
répondu TedEd 2012-02-24 17:06:27

toutes ces solutions sont acceptables pour des cas spécifiques, mais elles souffrent d'au moins un des deux problèmes possibles:

  1. Ils ne sont pas assez génériques -- ils veulent vous connaître, à l'avance, qu'une condition spécifique sera vrai de la page, vous allez (par exemple, un élément sera affiché)

  2. ils sont ouverts à une condition de course où vous utilisez un élément qui est réellement présent sur l'ancienne page, ainsi que la nouvelle page.

voici ma tentative d'une solution générique qui évite ce problème (en Python):

tout d'abord, une fonction "wait" Générique (utilisez un WebDriverWait si vous le souhaitez, je les trouve moches):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

ensuite, la solution repose sur le fait que selenium enregistre un numéro d'identification (interne) pour tous les éléments d'une page, y compris l'élément de premier niveau <html> . Lorsqu'un page mise à jour ou charge, il obtient un nouvel élément html avec un nouvel ID.

donc, en supposant que vous voulez cliquer sur un lien avec le texte "mon lien" par exemple:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

pour plus de Pythonic, réutilisable, aide Générique, vous pouvez faire un gestionnaire de contexte:

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

Et alors vous pouvez l'utiliser sur à peu près n'importe quelle interaction de sélénium:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

je pense que c'est Pare-balles! Qu'en pensez-vous?

Plus d'info dans un blog post à ce sujet ici

11
répondu hwjp 2014-09-03 18:26:24

si vous voulez attendre qu'un élément spécifique se charge, vous pouvez utiliser la méthode isDisplayed() sur un RenderedWebElement :

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(Exemple: Les 5 Minutes Guide de mise en route )

9
répondu Tristan 2014-10-22 04:50:35

Imran réponse du rabâchage pour Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });
9
répondu Fin 2015-10-10 11:02:51

cela semble être une limitation sérieuse de WebDriver. Évidemment, attendre un élément n'implique pas que la page soit chargée, en particulier le DOM peut être entièrement construit (état onready) où JS est toujours en cours d'exécution et CSS et images sont toujours en cours de chargement.

je crois que la solution la plus simple est de mettre une variable JS sur l'événement onload après que tout soit initialisé et de vérifier et d'attendre cette variable JS dans le sélénium.

8
répondu sibidiba 2012-05-11 15:32:25

je suis surpris que les prédicats n'étaient pas le premier choix car vous savez généralement quel(s) élément (s) vous allez interagir ensuite sur la page que vous attendez de charger. Mon approche a toujours été de construire des prédicats/fonctions comme waitForElementByID(String id) et waitForElemetVisibleByClass(String className) , etc. et puis utilisez et réutilisez ceux-ci partout où j'en ai besoin, que ce soit pour un chargement de page ou un changement de contenu de page que j'attends.

par exemple,

dans ma classe d'essai:

driverWait.until(textIsPresent("expectedText");

dans ma classe d'essai parent:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

Bien que cela semble beaucoup, il prend soin de vérifier à maintes reprises pour vous et l'intervalle de la fréquence de vérification peuvent être définies à l'ultime temps d'attente avant d'expirer. De plus, vous réutiliserez ces méthodes.

dans cet exemple, la classe mère a défini et déclenché les classes WebDriver driver et WebDriverWait driverWait .

j'espère que cela aidera.

4
répondu Jack Mason 2015-10-10 10:57:34

Utiliser implicitement attendre attendre de chaque élément sur la page jusqu'à ce moment donné.

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

cette attente pour chaque élément sur la page pendant 30 secondes.

une autre attente est explicitement une attente ou une attente conditionnelle dans cette attente jusqu'à ce que l'État soit donné.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

dans l'id donner l'id de l'élément statique qui est affiché avec méfiance sur la page, dès que la page est chargée.

4
répondu Kuldeep Yadav 2016-02-24 05:54:46

attendre explicitement ou une attente conditionnelle dans cette attente jusqu'à l'état donné.

 WebDriverWait wait = new WebDriverWait(wb, 60);
 wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

cela attendra chaque élément web pendant 60 secondes.

Utiliser implicitement attendre attendre de chaque élément sur la page jusqu'à ce moment donné.

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

cela attendra chaque élément web pendant 60 secondes.

4
répondu Anuj Teotia 2018-09-25 01:33:44
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

vous pouvez passer du document à un élément, dans le cas où seule une partie d'un document est en cours de modification.

cette technique a été inspirée par la réponse de sincebasic.

3
répondu Marc 2013-09-27 19:45:54

SeleniumWaiter :

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

et à vous utilisez-le :

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}
3
répondu tudorluchy 2015-10-10 10:48:01

vous pouvez explicitement attendre qu'un élément apparaisse sur la page Web avant de pouvoir prendre n'importe quelle action (comme élément.cliquez sur())

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(new ExpectedCondition<WebElement>(){
        @Override
        public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
}});

C'est ce que j'ai utilisé pour un scénario similaire et ça marche très bien.

2
répondu anirus 2012-01-26 02:17:20

Ma manière simple:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }
2
répondu RichardK 2015-04-22 13:43:33

la meilleure façon d'attendre le chargement d'une page lors de l'utilisation des reliures Java pour WebDriver est d'utiliser le motif de conception de la Page Object avec PageFactory. Cela vous permet d'utiliser le AjaxElementLocatorFactory qui, pour le dire simplement, les actes mondial attendre pour tous vos éléments. Il a des limites sur les éléments tels que les drop-boxes ou les transitions javascript complexes, mais il réduira drastiquement la quantité de code nécessaire et accélérera les temps de test. Un bon exemple peut être trouvé dans ce blogpost. Base la compréhension de Java de base est supposée.

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html

2
répondu sonhu 2016-01-05 20:44:29

NodeJS Solution:

Dans Nodejs vous pouvez l'obtenir via des promesses...

Si vous écrivez ce code, vous pouvez être sûr que la page est complètement chargée lorsque vous arrivez à l'époque...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

si vous écrivez ce code, vous naviguerez, et le sélénium attendra 3 secondes...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

De Sélénium de la documentation:

ce.get (url ) → Thenable

planifie une commande pour naviguer vers L'URL donnée.

renvoie une promesse qui sera résolue lorsque le document aura chargement terminé .

Documentation Sur Le Sélénium (Nodejs)

2
répondu sidanmor 2016-12-24 21:28:19

vous pouvez utiliser la méthode existante ci-dessous pour définir l'Heure de pageeLoadTimeout dans l'exemple ci-dessous si la page prend plus de 20 secondes à charger, alors il lancera une exception de page recharger

 WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
2
répondu Arpan Saini 2017-01-11 23:13:34

vous pouvez utiliser wait. il y a essentiellement 2 types d'attente dans le sélénium

  • attente implicite
  • attente explicite

- attente implicite

C'est très simple s'il vous plaît voir la syntaxe ci-dessous:

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

- attente explicite

attendre explicitement ou conditionnel dans cette attente jusqu'à compte tenu de la condition se produit.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

vous pouvez utiliser d'autres propriétés comme visblityOf() , visblityOfElement()

1
répondu iamsankalp89 2017-09-26 08:52:34

fonction Appel ci-dessous

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
1
répondu Shubham Jain 2018-02-02 10:00:01
driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);
0
répondu Ran Adler 2013-06-20 12:52:22

Le plus simple est d'attendre juste pour quelques élément qui apparaîtra sur la page chargée.

si vous souhaitez cliquer sur un bouton déjà après que la page est chargée, vous pouvez utiliser attendre et cliquer:

await().until().at.most(20, TimeUnit.Seconds).some_element.isDisplayed(); // or another condition
getDriver().find(some_element).click;
0
répondu Michau 2015-09-15 13:37:41

Comment obtenir le Sélénium attendre pour le chargement de la page après un clic prévoit ce qui suit approche intéressante:

  1. conservez une référence à un WebElement provenant de l'ancienne page.
  2. cliquez sur le lien.
  3. continuer à invoquer les opérations sur le WebElement jusqu'à ce que StaleElementReferenceException soit lancé.

code échantillon:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});
0
répondu Gili 2015-10-10 11:00:17

utiliser une condition si et pour l'un des éléments présents

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
0
répondu iam_muqshid 2016-06-12 19:05:09

vous pouvez essayer ce code pour laisser la page se charger complètement jusqu'à ce que l'élément soit trouvé.

public void waitForBrowserToLoadCompletely() {
    String state = null;
    String oldstate = null;
    try {
        System.out.print("Waiting for browser loading to complete");

        int i = 0;
        while (i < 5) {
            Thread.sleep(1000);
            state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
            System.out.print("." + Character.toUpperCase(state.charAt(0)) + ".");
            if (state.equals("interactive") || state.equals("loading"))
                break;
            /*
             * If browser in 'complete' state since last X seconds. Return.
             */

            if (i == 1 && state.equals("complete")) {
                System.out.println();
                return;
            }
            i++;
        }
        i = 0;
        oldstate = null;
        Thread.sleep(2000);

        /*
         * Now wait for state to become complete
         */
        while (true) {
            state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
            System.out.print("." + state.charAt(0) + ".");
            if (state.equals("complete"))
                break;

            if (state.equals(oldstate))
                i++;
            else
                i = 0;
            /*
             * If browser state is same (loading/interactive) since last 60
             * secs. Refresh the page.
             */
            if (i == 15 && state.equals("loading")) {
                System.out.println("\nBrowser in " + state + " state since last 60 secs. So refreshing browser.");
                driver.navigate().refresh();
                System.out.print("Waiting for browser loading to complete");
                i = 0;
            } else if (i == 6 && state.equals("interactive")) {
                System.out.println(
                        "\nBrowser in " + state + " state since last 30 secs. So starting with execution.");
                return;
            }

            Thread.sleep(4000);
            oldstate = state;

        }
        System.out.println();

    } catch (InterruptedException ie) {
        ie.printStackTrace();
    }
}
0
répondu ANarula 2016-10-20 14:40:23
private static void checkPageIsReady(WebDriver driver) {
        JavascriptExecutor js = (JavascriptExecutor) driver;

        // Initially bellow given if condition will check ready state of page.
        if (js.executeScript("return document.readyState").toString().equals("complete")) {
            System.out.println("Page Is loaded.");
            return;
        }

        // This loop will rotate for 25 times to check If page Is ready after
        // every 1 second.
        // You can replace your value with 25 If you wants to Increase or
        // decrease wait time.
        for (int i = 0; i < 25; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            // To check page ready state.
            if (js.executeScript("return document.readyState").toString().equals("complete")) {
                break;
            }
        }
    }
0
répondu Prasobh.K 2016-10-23 04:21:12

vous pouvez utiliser cet extrait de code pour la page à charger:

    IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00));
    wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

ou vous pouvez utiliser serveur pour tout élément à charger et devenir visible / cliquable sur cette page, très probablement qui va être chargé à la fin du chargement comme:

    Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement));
    var element = GlobalDriver.FindElement(By.XPath(xpathOfElement));
    var isSucceededed = element != null;
0
répondu Mohsin Awan 2016-11-07 11:03:26