selenium-webdriver
Wacht
Zoeken…
Soorten wachten in Selenium WebDriver
Tijdens het uitvoeren van een webtoepassing moet rekening worden gehouden met de laadtijd. Als uw code toegang probeert te krijgen tot een element dat nog niet is geladen, genereert WebDriver een uitzondering en stopt uw script.
Er zijn drie soorten wachttijden:
- Impliciete wachttijden
- Expliciete wachttijden
- Vloeiend wacht
Impliciete wachttijden worden gebruikt om de wachttijd in het hele programma in te stellen, terwijl expliciete wachttijden alleen op specifieke porties worden gebruikt.
Impliciet wachten
Een impliciete wachttijd is om WebDriver te vertellen de DOM een bepaalde tijd te pollen bij het proberen een element of elementen te vinden als deze niet onmiddellijk beschikbaar zijn. Impliciete wachttijden zijn in principe uw manier om WebDriver de latentie te vertellen die u wilt zien als het opgegeven webelement niet aanwezig is waarnaar WebDriver op zoek is. De standaardinstelling is 0. Eenmaal ingesteld, wordt het impliciete wachten ingesteld voor de levensduur van de objectinstantie van WebDriver. Impliciet wachten wordt in het instantiëringsgedeelte van de code verklaard met behulp van het volgende fragment.
Voorbeeld in Java :
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// You need to import the following class - import java.util.concurrent.TimeUnit;
Voorbeeld in C # :
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(15));
Dus in dit geval vertelt u WebDriver dat het 15 seconden moet wachten in het geval dat een gespecificeerd element niet beschikbaar is in de UI (DOM).
Expliciet wachten
U kunt instanties tegenkomen wanneer een element meer tijd nodig heeft om te laden. Impliciet wachten instellen voor dergelijke gevallen heeft geen zin, omdat de browser onnodig voor elk element op dezelfde tijd wacht, waardoor de automatiseringstijd toeneemt. Expliciet wachten helpt hier door impliciet wachten helemaal te omzeilen voor enkele specifieke elementen.
Expliciete wachttijden zijn intelligente wachttijden die beperkt zijn tot een bepaald webelement. Door expliciet te wachten, vertelt u WebDriver in feite dat het maximaal X eenheden van tijd moet wachten voordat het opgeeft.
Expliciete wachttijden worden uitgevoerd met de klassen WebDriverWait en ExpectedConditions. In het onderstaande voorbeeld wachten we tot 10 seconden totdat een element waarvan de ID gebruikersnaam is, zichtbaar wordt voordat we verdergaan met de volgende opdracht. Hier zijn de stappen.
Voorbeeld in Java :
//Import these two packages:
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
//Declare a WebDriverWait variable. In this example, we will use myWaitVar as the name of the variable.
WebDriverWait myWaitVar = new WebDriverWait(driver, 30);
//Use myWaitVar with ExpectedConditions on portions where you need the explicit wait to occur. In this case, we will use explicit wait on the username input before we type the text tutorial onto it.
myWaitVar.until(ExpectedConditions.visibilityOfElementLocated(By.id(“username”)));
driver.findElement(By.id(“username”)).sendKeys(“tutorial”);
De klasse ExpectedConditions heeft een aantal vooraf gedefinieerde algemene voorwaarden om op een element te wachten. Klik hier voor een lijst van deze voorwaarden in Java-binding.
Voorbeeld in C # :
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.PhantomJS;
// You can use any other WebDriver you want, such as ChromeDriver.
using (var driver = new PhantomJSDriver())
{
driver.Navigate().GoToUrl("http://somedomain/url_that_delays_loading");
// We aren't going to use it more than once, so no need to declare this a variable.
new WebDriverWait(driver, TimeSpan.FromSeconds(10))
.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));
// After the element is detected by the previous Wait,
// it will display the element's text
Console.WriteLine(driver.FindElement(By.Id("element-id")).Text);
}
In dit voorbeeld wacht het systeem 10 seconden totdat het element zichtbaar is. Als het element na de time-out niet zichtbaar is, gooit de WebDriver een WebDriverTimeoutException
.
Let op: als het element zichtbaar is vóór de time-out van 10 seconden, gaat het systeem onmiddellijk verder voor verder proces.
Vloeiend wachten
In tegenstelling tot impliciet en expliciet wachten, gebruikt vloeiend wachten twee parameters. Time-outwaarde en polling-frequentie. Laten we zeggen dat we een time-outwaarde hebben van 30 seconden en een polling-frequentie van 2 seconden. WebDriver controleert na elke 2 seconden op het element tot de time-outwaarde (30 seconden). Nadat de time-outwaarde zonder enig resultaat is overschreden, wordt een uitzondering gegenereerd. Hieronder is een voorbeeldcode die de implementatie van vloeiend wachten laat zien.
Voorbeeld in Java :
Wait wait = new FluentWait(driver).withTimeout(30, SECONDS).pollingEvery(2, SECONDS).ignoring(NoSuchElementException.class);
WebElement testElement = wait.until(new Function() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("testId"));
}
});
Een ander voordeel van vloeiend wachten is dat we specifieke soorten uitzonderingen (bijv. NoSuchElementExceptions) tijdens het wachten kunnen negeren. Vanwege al deze voorzieningen is vloeiend wachten nuttig in AJAX-toepassingen en in scenario's waarin de laadtijd van elementen vaak fluctueert. Strategisch gebruik van vloeiend wachten verbetert de automatisering aanzienlijk.
Verschillende soorten expliciete wachtvoorwaarden
In expliciet wachten, verwacht je dat er een toestand zal gebeuren. U wilt bijvoorbeeld wachten tot een element klikbaar is.
Hier is een demonstratie van enkele veel voorkomende problemen.
Let op: in al deze voorbeelden kunt u elke By
als locator gebruiken, zoals classname
, xpath
, link text
, tag name
of cssSelector
Wacht tot het element zichtbaar is
Als het bijvoorbeeld even duurt voordat uw website is geladen, kunt u wachten tot de pagina is geladen en uw element zichtbaar is voor de WebDriver.
C #
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));
Java
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("element-id")));
Wacht tot het element niet meer zichtbaar is
Hetzelfde als voorheen, maar dan omgekeerd.
C #
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.Id("element-id")));
Java
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("element-id")));
Wacht tot tekst aanwezig is in het opgegeven element
C #
IWebElement element = driver.FindElement(By.Id("element-id"));
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.TextToBePresentInElement(element, "text"));
Java
WebElement element = driver.findElement(By.id("element-id"));
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.textToBePresentInElement(element, "text"));
Als u naar de bovenstaande link gaat, ziet u daar alle wachtcondities.
Het verschil tussen het gebruik van deze wachtcondities zit in de invoerparameter.
Dat betekent dat u het WebElement moet doorgeven als de invoerparameter WebElement is, u moet de elementlocator doorgeven als het de By-locator als invoerparameter neemt.
Kies verstandig wat voor soort wachttoestand u wilt gebruiken.
Wachten op afronding van Ajax-aanvragen
C #
using OpenQA.Selenium
using OpenQA.Selenium.Chrome;
using System.Threading;
namespace WebDriver Tests
{
class WebDriverWaits
{
static void Main()
{
IWebDriver driver = new ChromeDriver(@"C:\WebDriver");
driver.Navigate().GoToUrl("page with ajax requests");
CheckPageIsLoaded(driver);
// Now the page is fully loaded, you can continue with further tests.
}
private void CheckPageIsLoaded(IWebDriver driver)
{
while (true)
{
bool ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
return;
Thread.Sleep(100);
}
}
}
}
Dit voorbeeld is handig voor pagina's waar ajax-aanvragen worden gedaan, hier gebruiken we de IJavaScriptExecutor
om onze eigen JavaScript-code uit te voeren. Omdat het binnen een while
lus is, blijft het lopen tot ajaxIsComplete == true
en dus wordt de return-opdracht uitgevoerd.
We controleren of alle ajax-aanvragen zijn voltooid door te bevestigen dat jQuery.active
gelijk is aan 0
. Dit werkt omdat elke keer dat een nieuw Ajax-verzoek wordt gedaan, jQuery.active
wordt opgehoogd en elke keer dat een verzoek wordt aangevuld, dit wordt verlaagd. jQuery.active == 0
kunnen we afleiden dat wanneer jQuery.active == 0
alle Ajax-aanvragen moeten zijn voltooid.
Vloeiend wachten
Vloeiend wachten is een superklasse van expliciet wachten ( WebDriverWait
) die meer configureerbaar is omdat het een argument voor de WebDriverWait
kan accepteren. Ik zal impliciet wachten doorgeven, omdat het een best practice is om het te vermijden.
Gebruik (Java):
Wait wait = new FluentWait<>(this.driver)
.withTimeout(driverTimeoutSeconds, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS)
.ignoring(StaleElementReferenceException.class)
.ignoring(NoSuchElementException.class)
.ignoring(ElementNotVisibleException.class);
WebElement foo = wait.until(ExpectedConditions.presenceOfElementLocated(By.yourBy));
// or use your own predicate:
WebElement foo = wait.until(new Function() {
public WebElement apply(WebDriver driver) {
return element.getText().length() > 0;
}
});
Wanneer u Expliciet wachten gebruikt met de standaardwaarden, is dit gewoon een FluentWait<WebDriver>
met standaardwaarden van: DEFAULT_SLEEP_TIMEOUT = 500;
en het negeren van NotFoundException
.
Vloeiend wachten
Elke FluentWait-instantie definieert de maximale wachttijd voor een voorwaarde, evenals de frequentie waarmee de voorwaarde wordt gecontroleerd. Bovendien kan de gebruiker het wachten configureren om specifieke typen uitzonderingen tijdens het wachten te negeren, zoals NoSuchElementExceptions bij het zoeken naar een element op de pagina. Het is gekoppeld aan het stuurprogramma.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS) //actuall wait for the element to pe present
.pollingEvery(5, SECONDS) //selenium will keep looking for the element after every 5seconds
.ignoring(NoSuchElementException.class); //while ignoring this condition
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.id("username"));