Wacht op paginabelasting in Selenium

Hoe maak je selenium 2.0 wachten op de pagina om te laden?


Antwoord 1, Autoriteit 100%

U kunt ook pageloaded controleren met behulp van de volgende code

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

Antwoord 2, Autoriteit 69%

Gebruik klasse webdriverwait

Zie ook hier

U kunt verwachten dat u een element laat zien. Iets zoals in 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"));

Antwoord 3, Autoriteit 28%

Als u het impliciete wacht van het stuurprogramma instelt, belt u de findelementMethode op een element dat u verwacht op de geladen pagina te staan, moet de WebDriver voor dat element uitpoppen totdat deze het element of bereikt de time-outwaarde.

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

Bron: impliciet-wacht


Antwoord 4, Autoriteit 25%

Over het algemeen moet bij Selenium 2.0 de webdriver de controle over de aanroepende code pas teruggeven als is vastgesteld dat de pagina is geladen. Als dit niet het geval is, kunt u waitforelemementaanroepen, die rondloopt met het aanroepen van findelementtotdat het wordt gevonden of een time-out optreedt (time-out kan worden ingesteld).


Antwoord 5, autoriteit 17%

Ruby-implementatie:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}

Antwoord 6, autoriteit 15%

U kunt de regel System.outverwijderen. Het is toegevoegd voor foutopsporingsdoeleinden.

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

Antwoord 7, autoriteit 14%

Al deze oplossingen zijn geschikt voor specifieke gevallen, maar ze hebben ten minste één van de volgende mogelijke problemen:

  1. Ze zijn niet generiek genoeg — ze willen dat je van tevoren weet dat een bepaalde voorwaarde geldt voor de pagina die je gaat bezoeken (er wordt bijvoorbeeld een element weergegeven)

  2. Ze staan open voor een race-conditie waarbij je een element gebruikt dat zowel op de oude pagina als op de nieuwe pagina aanwezig is.

Hier is mijn poging tot een generieke oplossing die dit probleem vermijdt (in Python):

Ten eerste een generieke “wacht”-functie (gebruik een WebDriverWait als je wilt, ik vind ze lelijk):

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__))

Vervolgens berust de oplossing op het feit dat selenium een (intern) id-nummer registreert voor alle elementen op een pagina, inclusief het <html>-element op het hoogste niveau. Wanneer een pagina wordt vernieuwd of geladen, krijgt deze een nieuw html-element met een nieuwe ID.

Dus, ervan uitgaande dat u op een link met de tekst “mijn link” wilt klikken, bijvoorbeeld:

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)

Voor een meer Pythonische, herbruikbare, generieke helper, kun je een contextmanager maken:

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)

En dan kun je het gebruiken voor vrijwel elke interactie met selenium:

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

Ik denk dat dat kogelvrij is! Wat denk je?

Meer info in een blog hierover hier


Antwoord 8, autoriteit 8%

Je kunt ook de klasse: ExpectedConditionsgebruiken om expliciet te wachten tot een element op de webpagina verschijnt voordat je actie kunt ondernemen voor verdere acties

Je kunt de klasse ExpectedConditionsgebruiken om te bepalen of een element zichtbaar is:

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

Zie ExpectedConditions class Javadocvoor een lijst van alle voorwaarden die u kunt controleren.


Antwoord 9, autoriteit 8%

Imrans antwoord herhaald voor 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");
        }
    });

Antwoord 10, autoriteit 7%

Dit lijkt een serieuze beperking van webdriver. Uiteraard zal wachten op een element niet impliceert dat de pagina wordt geladen, in het bijzonder de DOM kan volledig worden gebouwd (onredige staat) waarbij JS nog steeds uitvoert en CSS en afbeeldingen nog steeds laden.

Ik ben van mening dat de eenvoudigste oplossing is om een ​​JS-variabele in te stellen op de onloadgebeurtenis nadat alles is geïnitialiseerd en controleer en wacht op deze JS-variabele in Selenium.


Antwoord 11, Autoriteit 6%

Als u wilt wachten op een specifiek element om te laden, kunt u de isDisplayed()-methode gebruiken op een 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;
    }
}

(Voorbeeld van de 5 minuten aan de slaggids )


Antwoord 12, Autoriteit 6%

Hier is een Java 8-versie van de momenteel Meest geüpbaar antwoord :

WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));

waar myDriveris een WebDriverobject (eerder gedeclareerd).

Opmerking: Houd er rekening mee dat deze methode (document.readyState) alleen de DOM controleert.


Antwoord 13, autoriteit 6%

Expliciet wachten of voorwaardelijk wachten in deze wacht tot deze voorwaarde wordt gegeven.

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

Dit wacht 60 seconden op elk webelement.

Gebruik impliciet wachten op wachten van elk element op de pagina tot die tijd.

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

Dit wacht 60 seconden op elk webelement.


Antwoord 14, autoriteit 5%

Man al deze antwoorden vereisen te veel code. Dit zou een simpele zaak moeten zijn, aangezien het vrij gewoon is.

Waarom niet gewoon wat simpel Javascript met de webdriver injecteren en controleren.
Dit is de methode die ik gebruik in mijn webscraper-klasse. Het Javascript is vrij eenvoudig, zelfs als je het niet weet.

def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.
    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    ready_state = self.driver.execute_script('return document.readyState')
    if ready_state == 'loading':
        self.logger.info("Loading Page...")
    elif ready_state == 'interactive':
        self.logger.info("Page is interactive")
    elif ready_state == 'complete':
        self.logger.info("The page is fully loaded!")
    return ready_state

Antwoord 15, autoriteit 4%

Het verbaast me dat predikaten niet de eerste keuze waren, omdat je meestal weet met welk(e) element(en) je vervolgens interactie zult hebben op de pagina die je wacht om te laden. Mijn benadering is altijd geweest om predikaten/functies uit te bouwen zoals waitForElementByID(String id)en waitForElemetVisibleByClass(String className), enz. en deze vervolgens te gebruiken en opnieuw te gebruiken waar ik ze nodig heb , of het nu gaat om het laden van een pagina of een wijziging van de pagina-inhoud waar ik op wacht.

Bijvoorbeeld

In mijn testklas:

driverWait.until(textIsPresent("expectedText");

In mijn testklas ouder:

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

Hoewel dit veel lijkt, zorgt het ervoor dat u herhaaldelijk wordt gecontroleerd
en het interval voor hoe vaak te controleren kan worden ingesteld, samen met de ultieme
wachttijd voor time-out. U zult dergelijke methoden ook hergebruiken.

In dit voorbeeld heeft de bovenliggende klasse de WebDriver driveren de WebDriverWait driverWaitgedefinieerd en geïnitieerd.

Ik hoop dat dit helpt.


Antwoord 16, autoriteit 4%

Gebruik impliciet wachten op wachten van elk element op de pagina tot een bepaalde tijd.

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

dit wacht 30 seconden op elk element op de pagina.

Een andere wachttijd is Expliciet wachten of voorwaardelijk wachten in deze wachttijd tot de gegeven voorwaarde.

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

Geef in id een statische element-id op die voorzichtig op de pagina wordt weergegeven, zodra de pagina is geladen.


Antwoord 17, autoriteit 3%

De beste manier om te wachten op het laden van pagina’s bij gebruik van de Java-bindingen voor WebDriver, is door het ontwerppatroon Page Object met PageFactory te gebruiken. Dit stelt je in staat om de AjaxElementLocatorFactoryte gebruiken die, om het te zeggen, simpelweg fungeert als een globale wachttijd voor al je elementen. Het heeft beperkingen op elementen zoals drop-boxes of complexe javascript-overgangen, maar het zal de hoeveelheid benodigde code drastisch verminderen en de testtijden versnellen. Een goed voorbeeld vind je in deze blogpost. Basiskennis van Core Java wordt verondersteld.

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


Antwoord 18, autoriteit 3%

Bel onderstaande functie in je script aan, dit wacht tot de pagina niet is geladen met javascript

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}

Antwoord 19, autoriteit 3%

NodeJS-oplossing:

In Nodejskun je het krijgen via beloften…

Als u deze code schrijft, kunt u er zeker van zijn dat de pagina volledig is geladen wanneer u bij de dan…

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

Als je deze code schrijft, navigeer je en wacht selenium 3 seconden…

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...

Van Selenium-documentatie (Nodejs ):

this.get( url ) → Thenable<undefined>

Plant een opdracht om naar de opgegeven URL te navigeren.

Retourneert een belofte die zal worden opgelost wanneer het document klaar is met laden.


Antwoord 20, autoriteit 3%

U kunt de onderstaande bestaande methode gebruiken om de pageLoadTimeoutin te stellen. Als in het onderstaande voorbeeld de pagina meer dan 20 seconden nodig heeft om te laden, wordt een uitzondering voor het opnieuw laden van de pagina gegenereerd:

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

Antwoord 21, autoriteit 2%

/**
 * 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;
        }
    });
}

U kunt het document wijzigen in een element, in het geval dat slechts een deel van een document wordt gewijzigd.

Deze techniek is geïnspireerd op het antwoord van Sincebasic.


Antwoord 22, autoriteit 2%

SeleniumOber:

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

En voor jou gebruik het:

_waiter = new SeleniumWaiter(_driver);
try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}

Antwoord 23

Mijn eenvoudige manier:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;
        while (System.currentTimeMillis() < end) {
            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }

Antwoord 24

De beste manier die ik heb gezien is om de stalenessOfExpectedCondition te gebruiken, om te wachten tot de oude pagina oud wordt.

Voorbeeld:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

Het wacht tien seconden totdat de oude HTML-tag verouderd is en genereert vervolgens een uitzondering als dit niet gebeurt.


Antwoord 25

Ik gebruik node + selenium-webdriver (welke versie nu 3.5.0 is). wat ik hiervoor doe is:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))

Antwoord 26

U kunt wachten gebruiken. er zijn in principe 2 soorten wachten in selenium

  • Impliciet wachten
  • Expliciet wachten

– Impliciet wachten

Dit is heel eenvoudig, zie onderstaande syntaxis:

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

– Expliciet wachten

Expliciet wachten of voorwaardelijk wachten in deze wacht totdat de gegeven voorwaarde is opgetreden.

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

U kunt andere eigenschappen gebruiken, zoals visblityOf(), visblityOfElement()


Antwoord 27

Als iemand selenide gebruikt:

public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);

Meer voorwaarden vindt u hier:
http://selenide.org/javadoc/3.0/com/codeborne/ selenide/Condition.html


Antwoord 28

In mijn geval heb ik het volgende gebruikt om de laadstatus van de pagina te kennen. In onze applicatie zijn ladende gif(‘s) aanwezig en ik luister er als volgt naar om ongewenste wachttijden in het script te elimineren.

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

Waar het xpath de gif lokaliseert in de HTML DOM.
Hierna kunt u ook uw actiemethoden toepassen Klik.

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }

Antwoord 29

Je kunt expliciet wachten tot een element op de webpagina verschijnt voordat je actie kunt ondernemen (zoals element.click()):

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

Dit is wat ik voor een soortgelijk scenario heb gebruikt en het werkt prima.


Antwoord 30

Hoe u Selenium kunt laten wachten op het laden van de pagina na een klikbiedt de volgende interessante benadering:

  1. Winkel een verwijzing naar een WebElementvan de oude pagina.
  2. Klik op de link.
  3. Blijf bij het aanroepen van bewerkingen op de WebElementtot StaleElementReferenceExceptionwordt gegooid.

Voorbeeldcode:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});

Other episodes