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 findelement
Methode 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 waitforelemement
aanroepen, die rondloopt met het aanroepen van findelement
totdat 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.out
verwijderen. 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:
-
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)
-
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: ExpectedConditions
gebruiken om expliciet te wachten tot een element op de webpagina verschijnt voordat je actie kunt ondernemen voor verdere acties
Je kunt de klasse ExpectedConditions
gebruiken om te bepalen of een element zichtbaar is:
WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
Zie ExpectedConditions class Javadoc
voor 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 myDriver
is een WebDriver
object (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 driver
en de WebDriverWait driverWait
gedefinieerd 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 AjaxElementLocatorFactory
te 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 pageLoadTimeout
in 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 stalenessOf
ExpectedCondition 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:
- Winkel een verwijzing naar een
WebElement
van de oude pagina. - Klik op de link.
- Blijf bij het aanroepen van bewerkingen op de
WebElement
totStaleElementReferenceException
wordt 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;
}
});