Що ж, в попередніх постах було описано imlicit wait(неявне очікування) та fluent wait(впевнене очікування, хоча такий переклад — це радше відсебеньки), а це означає, що настав час для останнього з трьох — явного очікування. Як ви могли помітити у заголовку, пан автор обзиває його впевненим очікуванням швидкого приготування і на пергий погляд таке порівння могло б здатися дивним, втім після цього посту сподіваюся ви зрозумієте звідки воно взялося.
То що ж таке це явне очікування? Опираючись на документацію можна дати таке визначення: використовуючи explicit wait, вебдрайверу дається вказівка очіуквати, поки не виконається певна умова, перш ніж продовжити виконання коду. А ось і приклад такого очікування:
WebElement foo = new WebDriverWait(driver, Duration.ofSeconds(5))
.until(driver -> driver.findElement(By.name("foo")));
Здається знайомим, так? Воно й не дивно, адже WebDriverWait наслідує FluentWait.
Fluent wait:
WebElement foo = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(5))
.pollingEvery(Duration.ofSeconds(500))
.ignoring(NotFoundException.class)
.until(driver -> driver.findElement(By.name("foo")));
Explicit wait:
WebElement foo = new WebDriverWait(driver, Duration.ofSeconds(5))
.until(driver -> driver.findElement(By.name("foo")));
Загалом, явне очікування є специфікацією fluent wait яке ігнорує винятки NotFoundException
із встановленим за замовчування інтервалом між пошуками елементів, що дорівнює 500мс, а параметр, що відповідає за тривалість очікування встановлюється вручну. Гадаю тут вже починає ставати зрозумілим чому це очікування пан автор вирішим обізвати “впевненим очікуваннням швидкого приготування”. Втім, якщо вже розглядаємо таке приготування то й потрібно згадати про таку річ, як наперед задані умови для очікування, тобто про клас ExpectedConditions
. Звісно в ньому може не бути якоїсь специфічної умови, яка б підійшла в якомусь особливому випадку, проте цей клас містить умови, які будуть корисними у більшості ситуацій. Звісно в залежності від мови програмування яка використувується набір умов може відрізнятися, втім вони будуть мати певні спільні перевірки, наприклад:
Існування елемента
Видимість елемента
Видимий текст
Заголовок вікна тотожний
Звісно цей список не є вичерпним, втім за необхідності можна глянути їх відповідно до мови, що цікавить:
Java: org.openqa.selenium.support.ui.ExpectedConditions class
Python: selenium.webdriver.support.expected_conditions class
JavaScript: selenium-webdriver/lib/until module
До речі, якщо глянути код цих умов, наприклад для Java, то можна помітити, що вони подібні на ті умови, які описано в пості про fluent wait. Що ж, воно й не дивно адже, як згадувалося раніше, явне очікування є спеціалізацією впевненого очікування. Може здатися непоганою ідеєю використовувати умови з ExpectedConditions
у написанні умов для fluent wait, втім я, себто пан автор, не впевнений, що це буде раціональним, оскільки для цього існують явні очікування, а впевнене очікування, на думку автора, варто використовувати, коли явне не може вирішити проблему.
Отже, на цьому моменті вважаю, що тему про те, як готувати і з чим їсти очікування в Selenium можна вважатит вичерпаною. Також хотів би сказати, що на мою думку, поступовий перехід в темах від неявного очікування до явного через впевнене дає краще розуміння теми, ніж подача, яку можна зустріти в більшості постім на цю тему у вигляді: неявне → явне → впевнене. Особисто для мене, деякий час було загадкою як зміна тривалості не явного очікування може впливати на тривалість явного і справді, якщо не розглядати впевнене очікування чи умови, які описані у класі ExpectedConditions
такий зв’язок може здаватися незрозумілим, втім як тільки розглянути ці моменти все одразу стає очевидно.
І за традицією приклад:
WebElement h1 = driver.findElement(By.tagName("h1"));
System.out.println("Header text: " + h1.getText()); //Header text: Implicit Wait Example
WebElement firstParagraph = driver.findElement(By.tagName("p"));
System.out.println("First paragraph text: " + firstParagraph.getText()); //First paragraph text: This loads with page
WebElement clickMe = driver.findElement(By.id("addNewContent"));
System.out.println("Button text: " + clickMe.getText()); //Button text: ClickMe
WebElement thirdParagraph = new WebDriverWait(driver, Duration.ofSeconds(11))
.until(ExpectedConditions.visibilityOfElementLocated(By.id("postponedForElevenSeconds"))); //Third paragraph text: Loaded after 11 seconds.