Посмотрел лекцию для начинающих автоматизировать с Selenium
Очень приветствую создание и распространение обучающего материала, это правильно и нужно! Правда есть "но".
К сожалению не обошлось в этом материале без принципиальных фактических ошибок. В частности часть про явные и неявные ожидания (explicit/implicit waits) лектор предваряет ремаркой о том, что тема про эти два вида ожидания довольная сложна для понимания, и немедленно подтверждает тезис тем, что путает их между собой и даёт неверное пояснение.
Давайте же разберёмся, в чем разница. Страница помощи Selenium-а абсолютно невнятно освещает этот вопрос, поэтому попробую проще своими словами.
Explicit Wait - явное (непосредственное, прямое) ожидание используется "здесь и сейчас" на один конкретный поиск элемента. В частности, даже паттерн "sleep" (ждать и ничего не делать) является примером explicit wait, но его применение не поощряется.
На практике рекомендуется использование WebDriverWait в сочетании с методами класса ExpectedConditions, которые позволяют сократить ожидание. Если элемент появился раньше времени, заданного при инициализации WebDriverWait - Selenium не будет ждать, а продолжит исполнение теста.
Пример кода на Java:
1 2 3 4 5 6 |
WebDriver driver = new FirefoxDriver(); driver.get("http://someurl"); // ждем до 10 секунд WebElement explicitWait = (new WebDriverWait(driver, 10)) // или пока не появился элемент с id=bar .until(ExpectedConditions.presenceOfElementLocated(By.id("bar"))); |
Implicit Wait - неявное (косвенное, скрытое) ожидание устанавливается один раз в коде вне операции поиска и действительно до изменения. Значение по умолчанию - 0, т.е. никакого ожидания. Implicit Wait применяется ко всем последующим операциям поиска неявно (т.е. скрытно, без указания напрямую в методе поиска, как мы видели в примере выше).
Пример на Java:
1 2 3 4 5 6 7 8 9 |
WebDriver driver = new FirefoxDriver(); // задает максимум 10 секунд ожидания для каждого поиска driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://someurl"); // ждёт до 10 секунд, пока элемент не будет найден WebElement elem1 = driver.findElement(By.id("elem1")); //... сто строк спустя... // тоже ждёт до 10 секунд WebElement elem2 = driver.findElement(By.id("elem2")); |
В обоих случаях тест упадет с ошибкой через 10 секунд, если элемент не появится к этому времени. Также в обоих случаях тест не будет ждать 10 секунд, если элемент появился сразу или через пару секунд. Оба способа настроены так, что Selenium регулярно опрашивает DOM в поиске элемента. Как регулярно? По своему внутреннему алгоритму, на который можно повлиять, но это выходит за рамки этого поста.
Единственная разница между Explicit и Implicit Waits заключается в том, что первый действителен только в для того поиска, где он определен, а второй - для всех последующих поисков.
Документация Seleniuma не рекомендует мешать в коде Explicit и Implicit Waits потому что тогда, будет сложно рассчитать настоящее максимальное ожидание. Как отменить установленный Implicit Wait? Очень просто - поставьте его обратно на 0.
Так понятнее?
Update. Попросили написать еще совет, что использовать. Абсолютно не претендую на то, что мой совет лучший. Но зато он - простой.
Используйте всегда 4 секунды Implicit Wait, не дожидаясь проблем. А остальное - только, если понимаете зачем.
Хочу поблагодарить Алексея Баранцева за разъяснения и уточнения моего понимания вопроса. Надеюсь, что я ничего не перепутал сам 🙂