Suche…


Arten des Wartens in Selenium WebDriver

Beim Ausführen einer Webanwendung muss die Ladezeit berücksichtigt werden. Wenn Ihr Code versucht, auf ein Element zuzugreifen, das noch nicht geladen ist, gibt WebDriver eine Ausnahme aus und Ihr Skript wird angehalten.

Es gibt drei Arten von Wartezeiten -

  • Implizite Wartezeiten
  • Explizite Wartezeiten
  • Fließende Wartezeiten

Implizite Wartezeiten werden verwendet, um die Wartezeit im gesamten Programm festzulegen, während explizite Wartezeiten nur für bestimmte Teile verwendet werden.


Implizite Wartezeit

Eine implizite Wartezeit ist, WebDriver anzuweisen, das DOM für eine bestimmte Zeit abzufragen, wenn versucht wird, ein Element oder Elemente zu finden, wenn diese nicht sofort verfügbar sind. Implizite Wartezeiten sind im Grunde Ihre Methode, um WebDriver die Latenzzeit mitzuteilen, die Sie sehen möchten, wenn das angegebene Webelement nicht vorhanden ist, nach dem WebDriver sucht. Die Standardeinstellung ist 0. Nach der Festlegung wird die implizite Wartezeit auf die Lebensdauer der WebDriver-Objektinstanz festgelegt. Implizites Warten wird im Instantiierungsteil des Codes mit dem folgenden Snippet deklariert.

Beispiel in Java :

driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
// You need to import the following class - import java.util.concurrent.TimeUnit;

Beispiel in C # :

driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(15));

In diesem Fall teilen Sie WebDriver mit, dass es 15 Sekunden warten sollte, wenn das angegebene Element nicht auf der Benutzeroberfläche (DOM) verfügbar ist.


Explizites Warten

Es kann vorkommen, dass ein Element mehr Zeit zum Laden benötigt. Das implizite Warten auf solche Fälle ist nicht sinnvoll, da der Browser für jedes Element die gleiche Zeit unnötig wartet und die Automatisierungszeit verlängert. Das explizite Warten hilft hier, indem es das implizite Warten auf bestimmte Elemente umgeht.

Explizite Wartezeiten sind intelligente Wartezeiten, die auf ein bestimmtes Webelement beschränkt sind. Mit expliziten Wartezeiten teilen Sie WebDriver im Wesentlichen so lange mit, wie lange es dauert, um X-Einheiten zu warten, bevor es aufgibt.

Explizite Wartezeiten werden mit den Klassen WebDriverWait und ExpectedConditions ausgeführt. Im folgenden Beispiel werden wir bis zu 10 Sekunden warten, bis ein Element, dessen ID Benutzername lautet, sichtbar werden, bevor wir mit dem nächsten Befehl fortfahren. Hier sind die Schritte.

Beispiel 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”);

Die ExpectedConditions-Klasse hat einige vordefinierte allgemeine Bedingungen, um auf ein Element zu warten. Klicken Sie hier , um eine Liste dieser Bedingungen in der Java-Bindung anzuzeigen.

Beispiel 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 diesem Beispiel wartet das System 10 Sekunden, bis das Element sichtbar ist. Wenn das Element nach dem Timeout nicht sichtbar ist, gibt der WebDriver eine WebDriverTimeoutException .

Bitte beachten Sie: Wenn das Element vor dem Timeout von 10 Sekunden sichtbar ist, fährt das System sofort mit der weiteren Verarbeitung fort.


Fließend warten

Im Gegensatz zum impliziten und expliziten Warten werden beim fließenden Warten zwei Parameter verwendet. Timeout-Wert und Abrufhäufigkeit. Nehmen wir an, wir haben einen Timeout-Wert von 30 Sekunden und eine Abfragefrequenz von 2 Sekunden. WebDriver sucht alle 2 Sekunden bis zum Timeout-Wert (30 Sekunden) nach einem Element. Nachdem der Timeout-Wert ohne Ergebnis überschritten wurde, wird eine Ausnahme ausgelöst. Nachfolgend finden Sie einen Beispielcode, der die Implementierung des fließenden Wartens veranschaulicht.

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

Ein weiterer Vorteil des fließenden Wartens ist, dass wir bestimmte Arten von Ausnahmen (z. B. NoSuchElementExceptions) während des Wartens ignorieren können. Aufgrund all dieser Vorkehrungen ist fließendes Warten in AJAX-Anwendungen sowie in Szenarien, in denen die Elementladezeit häufig schwankt, hilfreich. Der strategische Einsatz von fließendem Warten verbessert die Automatisierungsbemühungen erheblich.


Verschiedene Arten expliziter Wartebedingungen

Beim expliziten Warten erwarten Sie das Eintreten einer Bedingung. Sie möchten beispielsweise warten, bis ein Element anklickbar ist.

Hier sind einige häufige Probleme dargestellt.

Bitte beachten Sie: In all diesen Beispielen können Sie ein beliebiges By als Locator verwenden, beispielsweise classname , xpath , link text , tag name oder cssSelector


Warten Sie, bis das Element sichtbar ist

Wenn zum Beispiel das Laden Ihrer Website einige Zeit dauert, können Sie warten, bis die Seite vollständig geladen ist und Ihr Element für den WebDriver sichtbar ist.

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

Warten Sie, bis das Element nicht mehr sichtbar ist

Wie zuvor, aber umgekehrt.

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

Warten Sie, bis im angegebenen Element Text vorhanden ist

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

Wenn Sie zu dem angegebenen Link gehen, sehen Sie dort alle Wartebedingungen.

Der Unterschied zwischen der Verwendung dieser Wartebedingungen liegt in ihren Eingabeparametern.

Das bedeutet, dass Sie das WebElement übergeben müssen, wenn der Eingabeparameter WebElement lautet. Sie müssen den Element-Locator übergeben, wenn der By-Locator als Eingabeparameter verwendet wird.

Wählen Sie mit Bedacht, welche Art von Wartezeit Sie verwenden möchten.

Warten auf den Abschluss der Ajax-Anfragen

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

Dieses Beispiel ist nützlich für Seiten, auf denen Ajax-Anforderungen gestellt werden. Hier verwenden wir den IJavaScriptExecutor , um unseren eigenen JavaScript-Code auszuführen. Da es sich innerhalb einer while Schleife befindet, wird es solange ausgeführt, bis ajaxIsComplete == true und die return-Anweisung ausgeführt wird.

Wir prüfen, ob alle Ajax-Anforderungen abgeschlossen sind, indem jQuery.active bestätigen, dass jQuery.active gleich 0 . Dies funktioniert, weil jedes Mal, wenn eine neue Ajax-Anforderung erfolgt, jQuery.active inkrementiert wird und jedes Mal, wenn eine Anforderung ergänzt wird, diese dekrementiert wird. Daraus können wir ableiten, dass bei jQuery.active == 0 alle Ajax-Anforderungen abgeschlossen sein müssen.

Fließend warten

Fließendes Warten ist eine Superklasse des expliziten Wartens ( WebDriverWait ), die besser konfigurierbar ist, da sie ein Argument für die Wait-Funktion akzeptieren kann. Ich werde das implizite Warten weitergeben, da dies die beste Vorgehensweise ist , um es zu vermeiden.

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

Wenn Sie das explizite Warten mit seinen Standardwerten verwenden, ist es einfach ein FluentWait<WebDriver> mit den DEFAULT_SLEEP_TIMEOUT = 500; : DEFAULT_SLEEP_TIMEOUT = 500; und NotFoundException ignorieren.

Fließend warten

Jede FluentWait-Instanz definiert die maximale Wartezeit auf eine Bedingung sowie die Häufigkeit, mit der die Bedingung geprüft werden soll. Darüber hinaus kann der Benutzer das Warten so konfigurieren, dass bestimmte Arten von Ausnahmen während des Wartens ignoriert werden, z. B. NoSuchElementExceptions bei der Suche nach einem Element auf der Seite. Es ist dem Treiber zugeordnet.

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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow