Implicit Wait to globalne ustawienie sesji WebDrivera: każde wyszukanie elementu czeka na niego do podanego limitu. Explicit Wait to pętla w kodzie testu, która czeka na konkretny warunek, na przykład klikalność przycisku albo zniknięcie spinnera. Różnica explicit wait vs implicit wait sprowadza się więc do pytania: czekacie na element w ogóle, czy na stan, którego test naprawdę potrzebuje?
Ten tekst jest dla Was, jeśli piszecie testy w Selenium 4 w Javie i macie dość czerwonych buildów, które po ponownym uruchomieniu same robią się zielone. Wszystkie przykłady poniżej skompilowaliśmy i uruchomiliśmy 11.10.2026 na Selenium 4.51.0, JUnit 6.1.3 i Javie 25, z Chrome w trybie headless. Gdzie piszemy o czasach, podajemy wynik pomiaru, a nie wrażenie. Jeśli dopiero zaczynacie przygodę z tym narzędziem, najpierw przeczytajcie przewodnik Selenium: co to jest i od czego zacząć, a tu wróćcie, gdy pierwszy test zacznie losowo padać.
Spis treści
- Explicit Wait vs Implicit Wait: czym się różnią?
- Dlaczego testy w Selenium potrzebują waitów?
- Jak działa Implicit Wait w Selenium 4?
- Jak napisać Explicit Wait z WebDriverWait i Duration?
- Kiedy użyć Fluent Wait?
- Co się dzieje, gdy zmieszacie Implicit Wait i Explicit Wait?
- Który wait wybrać w Waszym projekcie?
- Jak ograniczyć flaky testy poza samymi waitami?
- Pełna lista źródeł
Explicit Wait vs Implicit Wait: czym się różnią?
Oba mechanizmy rozwiązują ten sam problem, czyli wyścig między testem a przeglądarką, ale robią to na innym poziomie. Implicit Wait działa po stronie sterownika i dotyczy tylko odnajdywania elementów. Explicit Wait działa po stronie Waszego kodu i może czekać na dowolny warunek, który da się wyrazić w Javie.
Źródło: dokumentacja Selenium „Waiting Strategies” i specyfikacja W3C WebDriver (szkic z 02.07.2026), sprawdzone 11.10.2026
Jedno sprostowanie, które często pada w starszych materiałach, także w poprzedniej wersji tego artykułu: Implicit Wait nie wydłuża testu, gdy element jest od razu na stronie. Dokumentacja Selenium mówi wprost, że sterownik zwraca element, gdy tylko go znajdzie. W naszym pomiarze findElement na istniejącym przycisku przy implicit wait 3 s trwał 12 ms. Implicit Wait działa też z findElements, tylko w mniej intuicyjny sposób, o czym za chwilę.
Dlaczego testy w Selenium potrzebują waitów?
Przeglądarka i test to dwa niezależne procesy. Polecenie driver.get() czeka na document.readyState równy „complete”, ale nowoczesne aplikacje doładowują dane już po tym momencie: tabela przychodzi z API, przycisk odblokowuje się po walidacji, spinner znika po sekundzie. Test, który kliknie za wcześnie, padnie, choć aplikacja działa poprawnie. Dokumentacja Selenium nazywa to wprost wyścigiem i jedną z głównych przyczyn niestabilnych testów.
Skala problemu z niestabilnymi testami
45%
naprawionych niestabilnych testów w badaniu Luo i in. dotyczyło czekania na operacje asynchroniczne (74 z 161 commitów)
1,5%
wszystkich uruchomień testów w Google kończy się wynikiem niestabilnym
16%
testów w Google ma jakiś poziom niestabilności
84%
przejść z zielonego na czerwony w CI Google dotyczy testu niestabilnego
Źródło: Luo, Hariri, Eloussi, Marinov, „An Empirical Analysis of Flaky Tests”, FSE 2014; Google Testing Blog, „Flaky Tests at Google and How We Mitigate Them”, 2016
Według badania Luo i współautorów z konferencji FSE 2014 kategoria „Async Wait” była największą grupą przyczyn: 74 ze 161 przeanalizowanych poprawek, czyli 45%. To samo badanie podaje, że 20 z 74 takich testów (27%) naprawiono, dokładając sleep, co tylko zmniejsza prawdopodobieństwo awarii, zamiast ją usunąć. Waity nie są więc kosmetyką, tylko lekarstwem na najczęstszą chorobę testów UI.
Google na swoim blogu testowym w 2016 roku podał, że około 1,5% wszystkich uruchomień testów daje wynik niestabilny, a prawie 16% testów ma jakiś poziom niestabilności. Te liczby dotyczą wszystkich testów, nie tylko Selenium, ale pokazują koszt: według tego samego wpisu 84% przejść z zielonego na czerwony w CI dotyczyło testu niestabilnego, więc ktoś musiał sprawdzić ręcznie, czy to błąd, czy szum. Szerzej o tym, gdzie automatyzacja zwraca się, a gdzie zaczyna kosztować, piszemy w tekście zalety i wady automatyzacji testów.
Jak działa Implicit Wait w Selenium 4?
Implicit Wait ustawiacie raz, zwykle zaraz po utworzeniu sterownika. Od Selenium 4, wydanego 13.10.2021 według bloga projektu, jedyną poprawną sygnaturą jest wersja z java.time.Duration. Stara wersja z TimeUnit została oznaczona jako przestarzała, a new WebDriverWait(driver, 30) z liczbą sekund nie skompiluje się w aktualnym Selenium. Poniżej zestawienie, które warto mieć pod ręką przy migracji starego frameworka.
// Selenium 3, dziś nie skompiluje się albo jest oznaczone jako przestarzałe
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver, 30);
new FluentWait<>(driver).withTimeout(15, TimeUnit.SECONDS);
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
// Selenium 4
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
new FluentWait<>(driver).withTimeout(Duration.ofSeconds(15));
WebDriver driver = new ChromeDriver(); // Selenium Manager pobiera sterownikZwróćcie uwagę na ostatnią linię. Od Selenium 4.6, ogłoszonego na blogu projektu 04.11.2022, sterownik przeglądarki pobiera i dopasowuje Selenium Manager, więc System.setProperty("webdriver.chrome.driver", ...) jest zbędne, a ręcznie podana ścieżka potrafi wręcz przypiąć Was do starej wersji chromedrivera po aktualizacji Chrome. Na stacji, na której przygotowaliśmy przykłady, Selenium Manager sam pobrał sterownik dla Chrome 154.
Wszystkie testy w tym artykule korzystają z tej samej klasy bazowej i strony testowej waity.html: spinner znika po 1,5 s, przycisk „Zamów” odblokowuje się po 1,5 s, a potwierdzenie zamówienia pojawia się 2 s po kliknięciu. Zależności Maven i szkielet klasy wyglądają tak:
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.51.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>6.1.3</version>
<scope>test</scope>
</dependency>
</dependencies>import org.junit.jupiter.api.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.*;
import java.nio.file.Path;
import java.time.Duration;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class WaityTest {
private WebDriver driver;
private final String strona = Path.of("src/test/resources/waity.html").toUri().toString();
@BeforeEach
void start() {
ChromeOptions opcje = new ChromeOptions();
opcje.addArguments("--headless=new");
driver = new ChromeDriver(opcje); // Selenium Manager sam dobiera chromedriver
driver.get(strona);
}
@AfterEach
void stop() {
driver.quit();
}
}Sam Implicit Wait to jedna linijka. Zwróćcie uwagę, że do kliknięcia i tak użyliśmy Explicit Wait, bo Implicit Wait czeka na obecność elementu w DOM, a nie na to, że da się go kliknąć. Przycisk „Zamów” istnieje od początku, tylko jest zablokowany i przykryty spinnerem.
@Test
void implicitWait() {
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
new WebDriverWait(driver, Duration.ofSeconds(5))
.until(ExpectedConditions.elementToBeClickable(By.id("zamow"))).click();
WebElement potwierdzenie = driver.findElement(By.id("potwierdzenie"));
assertEquals("Zamówienie nr 1042 przyjęte", potwierdzenie.getText());
}Specyfikacja W3C WebDriver ustawia domyślny implicit wait na 0, limit ładowania strony na 300 000 ms, a limit skryptu na 30 000 ms. Ten sam dokument pokazuje, że implicit wait działa nie tylko przy szukaniu elementów, ale też przy czekaniu, aż pole będzie edytowalne w komendach clear i sendKeys. To kolejny powód, dla którego globalny timeout potrafi zaskoczyć w miejscu, w którym nikt go nie szukał.
Pułapka, którą zmierzyliśmy
findElements z ustawionym implicit wait nie zwraca pustej listy od razu. Sterownik czeka cały limit, licząc, że coś się jeszcze pojawi. W naszym pomiarze z 11.10.2026 sprawdzenie „czy elementu na pewno nie ma” przy implicit wait 3 s trwało 3 111 ms, podczas gdy znalezienie istniejącego elementu zajęło 12 ms. Test, który dziesięć razy sprawdza nieobecność komunikatu o błędzie, płaci za to pół minuty. Tak, Selenium też potrafi być bardzo cierpliwy, kiedy najmniej tego chcecie.
Jak napisać Explicit Wait z WebDriverWait i Duration?
Explicit Wait tworzycie w miejscu, w którym test potrzebuje konkretnego stanu aplikacji. Klasa WebDriverWait przyjmuje sterownik i limit typu Duration, a metoda until powtarza warunek, aż zwróci on wartość różną od null i false albo skończy się czas. Domyślnie wyjątek NoSuchElementException jest w trakcie czekania ignorowany, więc nie musicie go łapać sami.
@Test
void explicitWait() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("spinner")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("zamow"))).click();
WebElement potwierdzenie = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("potwierdzenie")));
assertTrue(potwierdzenie.getText().contains("1042"));
}Ten test czeka na trzy różne rzeczy: zniknięcie spinnera, klikalność przycisku i widoczność potwierdzenia. Gotowe warunki z klasy ExpectedConditions, które najczęściej widzimy w naszych projektach, to:
elementToBeClickableprzed kliknięciem, bo sprawdza widoczność i to, że element jest włączonyvisibilityOfElementLocatedprzed odczytem tekstu albo asercją na treściinvisibilityOfElementLocateddla spinnerów, nakładek i toastów, które przykrywają stronętextToBePresentInElementLocated, gdy element istnieje od razu, a zmienia się tylko jego treśćurlContainsititleIspo przekierowaniu, zanim zaczniecie szukać elementów nowej stronyframeToBeAvailableAndSwitchToItialertIsPresentdla ramek i okien dialogowych
Dokumentacja Selenium pokazuje dziś warunek częściej jako wyrażenie lambda niż jako ExpectedConditions. To wygodne, gdy żaden gotowy warunek nie pasuje: lambda może zwrócić dowolny obiekt, a until odda go Wam jako wynik. Poniżej wariant, który czeka na tekst potwierdzenia i od razu go zwraca.
@Test
void explicitWaitZLambda() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(d -> d.findElement(By.id("zamow")).isEnabled());
driver.findElement(By.id("zamow")).click();
String tekst = wait.until(d -> {
List<WebElement> el = d.findElements(By.id("potwierdzenie"));
return el.isEmpty() ? null : el.get(0).getText();
});
assertEquals("Zamówienie nr 1042 przyjęte", tekst);
}W Javie domyślny interwał odpytywania WebDriverWait to 500 ms. Jeśli element pojawi się po 1,2 s, test pójdzie dalej najpóźniej po około 1,5 s, a nie po pełnym limicie. Właśnie dlatego limit Explicit Wait możecie ustawić hojnie, na przykład 10 s, bez spowalniania szczęśliwej ścieżki. Same asercje na wyniku oczekiwania opisujemy osobno w tekście o asercjach w testach automatycznych.
Kiedy użyć Fluent Wait?
Fluent Wait to ta sama pętla co Explicit Wait, tylko z pełną kontrolą nad konfiguracją. WebDriverWait jest zresztą podklasą FluentWait. Sięgajcie po niego, gdy potrzebujecie jednej z czterech rzeczy: innego interwału odpytywania, ignorowania dodatkowych wyjątków, własnego komunikatu przy przekroczeniu limitu albo czekania na coś, co nie jest sterownikiem.
@Test
void fluentWait() {
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofMillis(300))
.ignoring(NoSuchElementException.class)
.ignoring(ElementClickInterceptedException.class)
.withMessage("Przycisk Zamów nie dał się kliknąć w 10 s");
wait.until(d -> {
d.findElement(By.id("zamow")).click();
return true;
});
WebElement potwierdzenie = wait.until(d -> d.findElement(By.id("potwierdzenie")));
assertTrue(potwierdzenie.isDisplayed());
}W tym przykładzie warunek sam próbuje kliknąć przycisk. Gdy spinner jeszcze przykrywa stronę, Chrome zgłasza ElementClickInterceptedException, Fluent Wait go ignoruje i ponawia próbę co 300 ms. Przy limicie 10 s i interwale 300 ms warunek zostanie sprawdzony maksymalnie około 34 razy. Komunikat z withMessage trafi do raportu z testów, więc osoba analizująca błąd od razu wie, na co test czekał.
Uwaga na ignorowanie wyjątków. Jeśli dopiszecie do listy StaleElementReferenceException, upewnijcie się, że warunek wyszukuje element od nowa w każdej iteracji, tak jak w przykładzie powyżej. Ignorowanie wyjątku przy elemencie zapamiętanym poza lambdą sprawi, że test będzie czekał do końca limitu na coś, co już nigdy nie wróci.
Co się dzieje, gdy zmieszacie Implicit Wait i Explicit Wait?
Dokumentacja Selenium ostrzega: nie mieszajcie Implicit Wait i Explicit Wait, bo czasy oczekiwania stają się nieprzewidywalne, i podaje przykład, w którym implicit 10 s i explicit 15 s mogą dać timeout po 20 s. Sprawdziliśmy to na Selenium 4.51.0 i Chrome 154 na elemencie, którego nie ma na stronie.
@Test
void pomiarMieszaniaWaitow() {
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
long start = System.nanoTime();
assertThrows(TimeoutException.class,
() -> wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("nie-ma-mnie"))));
System.out.println("POMIAR implicit 10 s + explicit 15 s: "
+ (System.nanoTime() - start) / 1_000_000 + " ms");
}Nasz pomiar z 11.10.2026, Selenium 4.51.0, Chrome 154 headless
20,7 s
trwał timeout przy implicit 10 s i explicit 15 s, zamiast oczekiwanych 15 s
3,1 s
trwało findElements bez wyniku przy implicit wait 3 s
12 ms
trwało findElement na istniejącym elemencie przy implicit wait 3 s
6 z 6
testów z tego artykułu przeszło na Javie 25 i JUnit 6.1.3
Źródło: dane własne Quality Island, klasa WaityTest uruchomiona lokalnie, Maven 3.9.12
Skąd 20,7 s? Explicit Wait co 500 ms wywołuje findElement. Każde takie wywołanie czeka 10 s wewnątrz sterownika, bo tak ustawiliście implicit wait. Pętla sprawdza swój limit tylko między wywołaniami, więc pierwsze sprawdzenie kończy się po 10 s, drugie po kolejnych 10 s, i dopiero wtedy Explicit Wait zauważa, że przekroczył 15 s. Przy innych wartościach wynik będzie inny, i dokładnie o tę nieprzewidywalność chodzi w ostrzeżeniu dokumentacji.
Który wait wybrać w Waszym projekcie?
Z naszego doświadczenia przy budowie frameworków automatyzacji wynika prosta zasada: implicit wait ustawiony na 0, Explicit Wait w każdym miejscu, w którym test czeka na stan aplikacji. Najlepiej schowany w obiektach stron, a nie rozsiany po testach. Jak to poukładać w Page Object, pokazujemy w artykule o wzorcach projektowych w Selenium WebDriver.
Domyślnie
Explicit Wait
WebDriverWait z limitem 10 s w obiekcie strony. Warunek dobrany do akcji: klikalność przed kliknięciem, widoczność przed odczytem.
Wyjątek
Fluent Wait
Gdy element bywa przykryty, przeładowywany albo potrzebujecie własnego komunikatu i interwału odpytywania.
Ostrożnie
Implicit Wait
Tylko w małym skrypcie bez Explicit Wait. W frameworku z waitami jawnymi zostawcie 0, czyli wartość domyślną.
Nigdy
Thread.sleep
Za krótki sypie testami, za długi spowalnia cały pakiet. Według badania z FSE 2014 to łatka, nie poprawka.
Czy Implicit Wait ma jeszcze sens? W skrypcie na pół godziny, który ma przeklikać formularz i zrobić zrzut ekranu, jak najbardziej. W pakiecie regresji, który codziennie uruchamia setki testów w CI, koszt pułapek opisanych wyżej rośnie z każdym testem. Strategię waitów warto zapisać w zasadach Waszego zespołu, żeby każda nowa osoba nie wymyślała jej od nowa.
Jak ograniczyć flaky testy poza samymi waitami?
Waity usuwają największą grupę przyczyn, ale nie wszystkie. W badaniu Luo i współautorów kolejne kategorie to współbieżność i zależność od kolejności testów. U naszych klientów najczęściej widzimy pięć źródeł niestabilności, które wyglądają jak problem z czekaniem, a nim nie są:
- Kruche selektory. Test czeka poprawnie, ale na element znaleziony absolutną ścieżką XPath, która zmienia się przy każdej przebudowie layoutu. Jak pisać stabilne lokatory, opisujemy w tekście selektory w Selenium
- Wspólne dane testowe. Dwa testy równolegle zmieniają tego samego użytkownika. Każdy test powinien tworzyć własne dane
- Zależność od kolejności. Test przechodzi tylko po innym teście, który zostawił aplikację w odpowiednim stanie
- Animacje i przejścia CSS. Element jest widoczny, ale jeszcze się przesuwa. Pomaga czekanie na zakończenie animacji albo jej wyłączenie w środowisku testowym
- Środowisko. Zbyt słaby agent CI albo wspólna baza danych. Tu żaden wait nie pomoże, trzeba naprawić infrastrukturę
Więcej typowych błędów, od testów bez asercji po automatyzację wszystkiego przez UI, zebrała Strefa QA w tekście o najczęstszych antywzorcach w testowaniu. W projekcie dla Argos uporządkowanie automatyzacji i procesów QA skróciło regresję przed releasem z 5 dni do 10 godzin, a liczba błędów krytycznych na produkcji spadła o 46%, co opisujemy w case study Argos. Stabilne testy to warunek takiego wyniku, bo regresji, której nikt nie ufa, nikt też nie skróci.
Jeśli chcecie przećwiczyć waity, Page Object i uruchamianie testów w CI pod okiem trenera, zajrzyjcie na szkolenie Automatyzacja testów Selenium WebDriver. Osobom, które dopiero zaczynają pisać w Javie, polecamy wcześniej szkolenie Programowanie w języku Java dla testerów. Gdy problemem nie jest wiedza, tylko framework, który zespół odziedziczył, pomaga doradztwo w automatyzacji testów albo przejęcie budowy testów w ramach usługi automatyzacja testów UI.
Co zabrać z tego artykułu
01Implicit Wait czeka globalnie tylko na obecność elementu w DOM. Explicit Wait czeka lokalnie na dowolny warunek, który potrzebny jest testowi.
02W Selenium 4 wszystkie limity podajecie jako Duration. Składnia z TimeUnit i new WebDriverWait(driver, 30) to Selenium 3.
03Selenium Manager od wersji 4.6 sam pobiera sterownik, więc System.setProperty dla chromedrivera możecie usunąć.
04Nie mieszajcie waitów: w naszym pomiarze implicit 10 s i explicit 15 s dały timeout po 20,7 s.
05findElements przy ustawionym implicit wait czeka cały limit, zanim zwróci pustą listę.
06Fluent Wait wybierzcie, gdy potrzebujecie własnego interwału, ignorowanych wyjątków albo komunikatu w raporcie.
Źródło: dokumentacja Selenium 2026, pomiar Quality Island z 11.10.2026
Wasze testy Selenium padają losowo, a zespół traci zaufanie do automatyzacji? Pomożemy znaleźć przyczyny i ustabilizować framework.
Powiązane na blogu Quality Island
- Selektory w Selenium: 8 lokatorów, XPath, CSS i lokatory względne z kodem
- Wzorce projektowe w Selenium WebDriver: Page Object, Factory, Strategy z kodem Java
- Selenium: co to jest, jak działa i od czego zacząć automatyzację testów
- Asercja: co to jest i jak używać asercji w testach automatycznych
- Zalety i wady automatyzacji testów: kiedy się opłaca i jak policzyć ROI
Pełna lista źródeł
- Selenium, dokumentacja „Waiting Strategies”, wersja dla Selenium 4, dostęp 11.10.2026
- Selenium, dokumentacja „Expected Conditions”, dostęp 11.10.2026
- W3C, WebDriver, Working Draft z 02.07.2026, sekcje Timeouts i Element Retrieval
- Q. Luo, F. Hariri, L. Eloussi, D. Marinov, „An Empirical Analysis of Flaky Tests”, FSE 2014
- J. Micco, „Flaky Tests at Google and How We Mitigate Them”, Google Testing Blog, 2016
- Selenium, „Announcing Selenium 4”, blog projektu, 13.10.2021
- Selenium, „Introducing Selenium Manager”, blog projektu, 04.11.2022
- Quality Island, pomiar własny: klasa WaityTest, Selenium 4.51.0, JUnit 6.1.3, Java 25, Chrome 154 headless, 11.10.2026
- Quality Island, case study Argos, dane potwierdzone przez klienta