Oczekiwanie jawne i niejawne Selenium ze składnią

⚡ Inteligentne podsumowanie

Selenium Polecenia wait synchronizują skrypty automatyzacji z dynamicznym zachowaniem strony, zapobiegając błędom testów spowodowanym przez elementy ładowane asynchronicznie. W tym dokumencie wyjaśniono strategie oczekiwania niejawnego, jawnego i płynnego ze składnią WebDriver, działającą w oparciu o… Java przykłady kodu i praktyczne wskazówki dotyczące wyboru odpowiedniego oczekiwania na stabilne i niezawodne wykonanie testów.

  • ⚙️ FoundationZasada al: Zastosuj globalnie opcję Implicit Wait, aby WebDriver wstrzymał się na określony czas przed zgłoszeniem wyjątku NoSuchElementException.
  • 🎯 Cel wdrożenia: Użyj Explicit Wait z ExpectedConditions, aby wskazać elementy zależne od Ajaxa lub dynamicznych stanów widoczności.
  • 🔁 Zaawansowana technika: Skonfiguruj Fluent Wait z interwałami sondowania, aby obsługiwać elementy ładowane w nieprzewidywalnych momentach.
  • Strategia optymalizacji: Zastąp Thread.sleep oczekiwaniami warunkowymi, aby skrócić czas wykonywania i wyeliminować opóźnienia.
  • Wpływ na jakość: Wybranie właściwego oczekiwania bezpośrednio zmniejsza ryzyko wystąpienia niepewnych awarii i poprawia stabilność skryptu w różnych środowiskach.

Selenium Czekaj – niejawne i jawne ze składnią

In Selenium„Czekanie” odgrywa ważną rolę w przeprowadzaniu rzetelnych testów. W tym samouczku poznasz kluczowe aspekty i różnice między niejawnymi i jawnymi poleceniami oczekiwania w… Selenium, wraz z praktycznym wykorzystaniem Fluent Wait.

Dlaczego potrzebujemy poczekań Selenium?

Większość nowoczesnych aplikacji internetowych jest tworzona przy użyciu ajax oraz JAVASCRIPTGdy przeglądarka ładuje stronę, elementy, z którymi chcemy wejść w interakcję, mogą ładować się w różnych odstępach czasu.

Nie tylko utrudnia to identyfikację pierwiastka, ale także, jeśli pierwiastek nie zostanie zlokalizowany w czasie, Selenium rzuci Wyjątek ElementNotVisible. Selenium Funkcja waits rozwiązuje ten problem z synchronizacją, dając WebDriverowi zdefiniowane okno, w którym może znaleźć element, zanim wystąpi błąd.

Rozważmy scenariusz, w którym w tym samym teście używane są zarówno oczekiwania niejawne, jak i jawne. Załóżmy, że oczekiwanie niejawne ustawione jest na 20 sekund, a oczekiwanie jawne na 10 sekund.

Jeśli szukamy elementu rządzonego przez pewne Oczekiwane warunki (Jawne oczekiwanie) i jeśli element nie znajduje się w jawnym oknie 10 sekund, WebDriver wraca do niejawnego okna 20 sekund przed zgłoszeniem błędu Wyjątek ElementNotVisible.

Selenium WebDriver czeka

  1. Niejawne oczekiwanie
  2. Wyraźne oczekiwanie
  3. Płynne czekanie

Niejawne Czekanie Selenium

Niejawne Czekanie Selenium Nakazuje WebDriverowi odczekać określony czas przed zgłoszeniem wyjątku NoSuchElementException. Wartość domyślna to 0. Po skonfigurowaniu WebDriver odpytuje DOM przez ten czas, zanim zgłosi błąd. Selenium WebDriver odziedziczył koncepcję niejawnych oczekiwań od Watir.

W poniższym przykładzie deklarujemy niejawne oczekiwanie o czasie trwania 10 sekund. Jeśli element nie znajduje się w tym oknie, zgłaszany jest wyjątek.

Niejawna składnia oczekiwania (Selenium 4):

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
package guru.test99;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

public class AppTest {

    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.equals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }
        // close browser
        driver.close();
    }
}

Wyjaśnienie Code

W powyższym przykładzie rozważmy następujące stwierdzenie:

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

Selenium Wersja 4 zastąpiła starszą dwuargumentową sygnaturę (liczba całkowita plus TimeUnit) pojedynczym argumentem Duration. Klasa Duration obsługuje sekundy, minuty, milisekundy i inne jednostki czasu za pośrednictwem statycznych metod pomocniczych, takich jak Duration.ofSeconds, Duration.ofMillis i Duration.ofMinutes.

Wyraźne czekanie Selenium

Wyraźne czekanie Selenium Nakazuje WebDriverowi czekać na określone warunki (warunki oczekiwane) lub maksymalny czas oczekiwania przed zgłoszeniem wyjątku ElementNotVisibleException. Jest to inteligentniejsze oczekiwanie, ponieważ dotyczy tylko określonego elementu. Jawne oczekiwanie jest preferowane w stosunku do niejawnego oczekiwania, gdy test musi obsłużyć dynamicznie ładowaną zawartość Ajax.

Po wyraźnym zadeklarowaniu oczekiwania należy użyć Oczekiwane warunkilub możesz skonfigurować częstotliwość sondowania za pomocą Płynne czekanie. Unikaj używania Wątek.sleep(), ponieważ wstrzymuje wykonywanie poleceń bezwarunkowo i jest ogólnie uważane za złą praktykę.

W poniższym przykładzie tworzymy odniesienie do WebDriverCzekaj klasa, utwórz ją za pomocą Sterownik sieciowy odniesienie i skonfiguruj maksymalne okno na 20 sekund.

Jawna składnia oczekiwania (Selenium 4):

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
package guru.test99;

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Test;

public class AppTest2 {
    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.contentEquals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }
        WebElement guru99seleniumlink;
        guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
            By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
        guru99seleniumlink.click();
    }
}

Wyjaśnienie Code

Rozważ następujący kod:

WebElement guru99seleniumlink;
guru99seleniumlink = wait.until(ExpectedConditions.visibilityOfElementLocated(
    By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
guru99seleniumlink.click();

W tym przykładzie WebDriverWait skrypt czeka do 20 sekund, zgodnie z definicją WebDriverCzekaj klasa, aż do Oczekiwane warunki zostaną spełnione — w zależności od tego, co nastąpi wcześniej.

Powyżej Java kod czeka do 20 sekund na spełnienie warunku widocznośćZlokalizowanego elementu aby mogło być prawdziwe.

Można zastosować następujące oczekiwane warunki Selenium Jawne oczekiwanie:

  1. alertIsPresent()
  2. elementSelectionStateToBe()
  3. elementToBeClickable()
  4. elementToBeSelected()
  5. ramkaToBeAvailableAndSwitchToIt()
  6. niewidzialnośćOfTheElementLocated()
  7. niewidzialnośćElementuWithText()
  8. obecnośćOfAllElementsLocatedBy()
  9. obecnośćOfElementLocated()
  10. tekstToBePresentInElement()
  11. tekstToBePresentInElementLocated()
  12. tekstToBePresentInElementValue()
  13. tytułIs()
  14. tytułZawiera()
  15. widoczność()
  16. widocznośćOfAllElements()
  17. widocznośćOfAllElementsLocatedBy()
  18. widocznośćOfElementLocated()

Płynnie Zaczekaj Selenium

Płynnie Zaczekaj Selenium Definiuje maksymalny czas oczekiwania WebDrivera na warunek, a także częstotliwość odpytywania w celu weryfikacji tego warunku przed zgłoszeniem wyjątku ElementNotVisibleException. Fluent Wait sprawdza element w regularnych odstępach czasu, aż do znalezienia obiektu lub upłynięcia limitu czasu.

Częstotliwość: Powtarzalny cykl oceny stanu w regularnych odstępach czasu.

Rozważmy scenariusz, w którym element ładuje się w nieprzewidywalnych odstępach czasu. Element może załadować się w 10 sekund, 20 sekund lub dłużej. Jeśli zadeklarujemy jawnie 20-sekundowy czas oczekiwania, skrypt będzie czekał przez cały czas, zanim zakończy działanie. W takich przypadkach Fluent Wait jest idealnym wyborem, ponieważ odpytuje z określoną częstotliwością, aż do momentu znalezienia elementu lub upłynięcia limitu czasu.

Płynna składnia oczekiwania (Selenium 4):

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofSeconds(5))
    .ignoring(NoSuchElementException.class);

Starszy podpis akceptujący wartości całkowite plus jednostkę czasu został wycofany Selenium 3.11 i usunięto w Selenium 4. Obecnie zalecanym podejściem jest interfejs API oparty na czasie trwania przedstawiony powyżej.

package guru.test99;

import java.time.Duration;
import java.util.NoSuchElementException;
import java.util.function.Function;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.testng.annotations.Test;

public class AppTest3 {
    protected WebDriver driver;

    @Test
    public void guru99tutorials() throws InterruptedException {
        String eTitle = "Demo Guru99 Page";
        String aTitle = "";
        driver = new ChromeDriver();
        // launch Chrome and redirect it to the Base URL
        driver.get("https://demo.guru99.com/test/guru99home/");
        // Maximize the browser window
        driver.manage().window().maximize();
        // get the actual value of the title
        aTitle = driver.getTitle();
        // compare the actual title with the expected title
        if (aTitle.contentEquals(eTitle)) {
            System.out.println("Test Passed");
        } else {
            System.out.println("Test Failed");
        }

        Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(Duration.ofSeconds(30))
            .pollingEvery(Duration.ofSeconds(5))
            .ignoring(NoSuchElementException.class);

        WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
            }
        });
        // click on the selenium link
        clickseleniumlink.click();
        // close browser
        driver.close();
    }
}

Wyjaśnienie Code

Rozważ następujący kod:

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofSeconds(5))
    .ignoring(NoSuchElementException.class);

W powyższym przykładzie deklarujemy Fluent Wait z limitem czasu 30 sekund, częstotliwością odpytywania 5 sekund i ignorujemy Wyjątek NoSuchElement.

Rozważ następujący kod:

public WebElement apply(WebDriver driver) {
    return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
}

Ta funkcja identyfikuje WebElement na stronie (tutaj Selenium (link na stronie głównej). Z interwałem sondowania wynoszącym 5 sekund i limitem czasu 30 sekund, funkcja czekania sprawdza element co 5 sekund przez maksymalnie 30 sekund. Jeśli element znajduje się w tym oknie, skrypt kontynuuje działanie. W przeciwnym razie Wyjątek ElementNotVisible zostaje rzucony.

Sprawdź również: Selenium Samouczek IDE dla początkujących

Różnica między niejawnym oczekiwaniem a jawnym oczekiwaniem

Poniższa tabela przedstawia najważniejsze różnice między oczekiwaniem niejawnym a oczekiwaniem jawnym. Selenium.

Niejawne oczekiwanie Wyraźne oczekiwanie
Do wszystkich elementów skryptu stosowany jest domyślny czas oczekiwania. Jawny czas oczekiwania jest stosowany tylko do konkretnie określonych elementów docelowych.
W przypadku Implicit Wait, ExpectedConditions nie są określone dla elementu. W przypadku Explicit Wait należy zdefiniować ExpectedConditions dla elementu.
Zalecane, gdy elementy ładują się w ramach skonfigurowanego okna oczekiwania. Zalecane, gdy ładowanie elementów trwa dłużej i podczas sprawdzania stanu elementów, np. visibilityOfElementLocated, elementToBeClickable lub elementToBeSelected.
Ustaw raz i zastosuj przez cały cykl życia instancji WebDriver. Ustaw dla każdego elementu lub sprawdzenia, co zapewnia dokładniejszą kontrolę.

Jak wybrać odpowiednią strategię oczekiwania

Wybór właściwego polecenia wait ma bezpośredni wpływ na stabilność skryptu i czas wykonania. Użyj tego schematu decyzyjnego, aby wybrać odpowiednią opcję dla każdego scenariusza.

  1. Określ wzór obciążenia: Sprawdź, czy element pojawia się w ustalonym czasie, po odpowiedzi Ajax, czy w nieprzewidywalnych odstępach czasu. Stałe obciążenia wymagają trybu oczekiwania niejawnego (Implicit Wait), natomiast nieprzewidywalne obciążenia wymagają trybu oczekiwania płynnego (Fluent Wait).
  2. Unikaj mieszania oczekiwań jawnych i niejawnych: Połączenie tych dwóch czynników może spowodować nieoczekiwane opóźnienia, ponieważ dłuższe oczekiwanie może mieć decydujący wpływ. Selenium Dokumentacja zaleca korzystanie tylko z jednej strategii na sesję WebDriver.
  3. Domyślnie: Explicit. Czekaj na zawartość dynamiczną: Gdy strony opierają się na Ajaxie, renderowaniu warunkowym lub animacjach, Explicit Wait z ExpectedConditions kieruje uwagę dokładnie na element, który ma znaczenie.
  4. Użyj Fluent Wait dla zmiennego czasu: Jeśli czas ładowania elementów różni się między uruchomieniami, skonfiguruj Fluent Wait z interwałem sondowania. Sondowanie skraca całkowity czas oczekiwania w porównaniu z pojedynczym długim czasem oczekiwania.
  5. Zastąp Thread.sleep: Zakodowane na stałe sny spowalniają zestawy testów i ukrywają rzeczywiste problemy z czasem. Zastąp je oczekiwaniami warunkowymi, aby zapewnić szybkie i deterministyczne wykonywanie.
  6. Dostrój wartości limitu czasu: Zacznij od krótkich limitów czasu (5–10 sekund) i wydłużaj je tylko wtedy, gdy awarie wskazują na rzeczywiste wolne obciążenie. Długie domyślne limity czasu maskują regresję wydajności.
  7. Zachowaj oczekiwania w narzędziach pomocniczych: Centralizuj logikę oczekiwania w klasie pomocniczej, aby zmiany zasad dotyczących limitów czasu obowiązywały w całym zestawie testów.

Stosując się do tych wytycznych, inżynierowie automatycy mogą tworzyć odporne skrypty, które dostosowują się do rzeczywistego czasu działania aplikacji, nie stając się przy tym powolne ani kruche.

Typowe błędy, których należy unikać Selenium Czeka

Nawet doświadczeni testerzy wpadają w szereg powtarzających się pułapek podczas pracy z Selenium czeka. Unikanie tych problemów sprawia, że ​​skrypty są szybkie, deterministyczne i łatwe w utrzymaniu w różnych zespołach i środowiskach.

Pierwszym częstym błędem jest nadużywanie Thread.sleep. Zakodowana na stałe pauza zmusza skrypt do oczekiwania przez cały czas, niezależnie od faktycznej dostępności elementów, co wydłuża całkowity czas wykonania. Zastąp takie pauzy jawnymi lub płynnymi pauzami, aby skrypt kontynuował działanie w momencie spełnienia warunku.

Drugim błędem jest mieszanie niejawnych i jawnych waitów w tym samym teście. Te dwa mechanizmy mogą się na siebie nakładać, tworząc nieprzewidywalne, trudne do debugowania timeouty. Wybierz jedną strategię na sesję WebDriver i stosuj ją konsekwentnie.

Trzecim błędem jest ustawianie zbyt wysokich limitów czasu „na wszelki wypadek”. Długie okna domyślne ukrywają rzeczywiste problemy z wydajnością i spowalniają sprzężenie zwrotne w procesach ciągłej integracji. Zacznij od krótkich limitów czasu i wydłużaj je tylko wtedy, gdy logi błędów wykażą istnienie rzeczywistego problemu z czasem.

Sprawdź również: Selenium Samouczek dla początkujących: Naucz się WebDrivera w 7 dni

FAQ

Domyślny czas oczekiwania w Selenium WebDriver ma wartość 0 sekund. Sterownik nie wstrzymuje się w przypadku brakujących elementów, dopóki nie zostanie wywołana metoda implicitlyWait z niestandardową wartością Duration.

Thread.sleep wstrzymuje wykonywanie bezwarunkowo na ustalony czas, niezależnie od gotowości elementu. Wydłuża to całkowity czas wykonania, maskuje problemy z wydajnością i generuje niestabilne testy. Jawne i płynne oczekiwania są wznawiane w momencie spełnienia warunku.

Nie jest to zalecane. Selenium Dokumentacja ostrzega, że ​​połączenie obu strategii może powodować nieprzewidywalne czasy oczekiwania. Wybierz jedną strategię na sesję WebDriver, zazwyczaj Explicit Wait lub Fluent Wait, aby uzyskać bardziej przejrzyste zachowanie i łatwiejsze debugowanie.

Tak. Platformy testowe oparte na sztucznej inteligencji, takie jak Testim, Mabl i Functionize analizują czasy reakcji aplikacji i rekomendują wartości Explicit lub Fluent Wait. Zmniejszają one częstotliwość prób i błędów oraz dynamicznie dostosowują limity czasu na podstawie obserwowanego zachowania strony.

Silniki sztucznej inteligencji uczą się historycznych wzorców obciążenia i automatycznie dostosowują interwały sondowania lub okna limitu czasu. Gdy test wielokrotnie kończy się niepowodzeniem w pobliżu granicy czasowej, model wydłuża oczekiwanie lub przełącza się na bardziej inteligentny warunek, zmniejszając liczbę niestabilnych awarii w różnych przebiegach.

Podsumuj ten post następująco: