Как я могу попросить Selenium-WebDriver ждать несколько секунд в Java?

Я работаю над Java Selenium-WebDriver. Я добавил

driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

и

WebElement textbox = driver.findElement(By.id("textbox"));

потому что мои приложения занимают несколько секунд, чтобы загрузить пользовательский интерфейс. Поэтому я установил 2 секунды implicitwait. но я получил неспособный найти текстовое поле элемента

Затем добавьте Thread.sleep(2000);

Теперь он отлично работает. Какой из них лучше?

Ответ 1

Ну, есть два типа ожидания: явное и неявное ожидание. Идея явного ожидания

WebDriverWait.until(condition-that-finds-the-element);

Понятие неявного ожидания

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Вы можете получить разницу в деталях здесь.

В таких ситуациях я предпочел бы использовать явное ожидание (fluentWait в частности):

public WebElement fluentWait(final By locator) {
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElement(locator);
        }
    });

    return  foo;
};
Функция

fluentWait возвращает найденный веб-элемент. Из документации по fluentWait: Реализация интерфейса Wait, которая может иметь свой тайм-аут и интервал опроса, настроенный "на лету". Каждый экземпляр FluentWait определяет максимальное время ожидания условия, а также частоту проверки состояния. Кроме того, пользователь может настроить wait для игнорирования определенных типов исключений во время ожидания, например NoSuchElementExceptions при поиске элемента на странице. Подробности вы можете получить здесь

Использование fluentWait в вашем случае будет следующим:

WebElement textbox = fluentWait(By.id("textbox"));

Этот подход ИМХО лучше, поскольку вы точно не знаете, сколько времени ждать и в интервале опроса вы можете установить произвольное значение времени, через которое будет проверено присутствие элемента. С наилучшими пожеланиями.

Ответ 2

Если используется webdriverJs (node.js),

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

Приведенный выше код заставляет браузер ждать 5 секунд после нажатия кнопки.

Ответ 3

Этот поток немного старше, но я думал, что опубликую то, что я сейчас делаю (работа продолжается).

Хотя я все еще сталкиваюсь с ситуациями, когда система находится под большой нагрузкой, и когда я нажимаю кнопку отправки (например, login.jsp), все три условия (см. ниже) возвращают true, но на следующей странице (например, home.jsp) еще не приступил к загрузке.

Это общий метод ожидания, который принимает список ExpectedConditions.

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

Я определил различные повторно используемые Ожидаемые условия (три ниже). В этом примере три ожидаемых условия включают document.readyState = 'complete', no "wait_dialog" присутствует, и нет "прядильщиков" (запрашиваются элементы, указывающие данные aync).

Только одно из них может быть в общем случае применено ко всем веб-страницам.

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

В зависимости от страницы я могу использовать один или все из них:

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

Существуют также предопределенные ExpectedConditions в следующем классе: org.openqa.selenium.support.ui.ExpectedConditions

Ответ 4

Использование Thread.sleep(2000); - безусловное ожидание. Если ваш тест загружается быстрее, вам все равно придется ждать. Таким образом, в принципе использование implicitlyWait является лучшим решением.

Однако я не понимаю, почему implicitlyWait не работает в вашем случае. Вы оценили, действительно ли findElement занимает две секунды, прежде чем выбрасывать исключение. Если да, можете ли вы попытаться использовать условное ожидание WebDriver, как описано в this?

Ответ 5

Мне нравятся пользовательские условия. Здесь некоторый код в Python:

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

Всякий раз, когда вам нужно ждать, вы можете сделать это явно, проверяя существование определенного элемента (такой элемент может варьироваться от страницы к странице). find_elements_by_id возвращает список - пустой или нет, вы должны просто проверить.

Ответ 6

щелчок, кажется, блокирует? - здесь еще один способ подождать, если вы используете WebDriverJS:

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

Следующий код ждет после нажатия кнопки для загрузки следующей страницы и последующего захвата источника следующей страницы.

Ответ 7

Thread.sleep(5000);

Это действительно помогло мне, но исключение InterruptedException необходимо позаботиться. Так что лучше окружайте его с помощью try and catch:

try {
    Thread.sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

ИЛИ

Добавить объявление throws:

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

Я предпочел бы второй вариант, так как тогда можно использовать sleep() столько раз, сколько захочет, и избегать повторения блока try и catch каждый раз, когда использовался sleep().

Ответ 8

Иногда неявное ожидание, похоже, становится переопределенным, а время ожидания сокращается. [@Евгений.Польщиков] имел хорошую документацию на whys. Я нашел в своем тестировании и кодировании Selenium 2, что подразумеваемые ожидания хороши, но иногда вам приходится ждать явно.

Лучше избегать прямого вызова потока для сна, но иногда это не очень хорошо. Тем не менее, есть другие варианты поддержки селена, которые помогают. waitForPageToLoad и waitForFrameToLoad оказались особенно полезными.

Ответ 9

Неявно ждать и Thread.sleep Оба используются только для синхронизации.. но разница в том, что мы можем использовать Неявно ждать всей программы, но Thread.sleep будет работать только для этого единственного кода. Вот мое предложение - использовать Неявно ждать один раз в программе, когда каждый раз, когда ваша веб-страница будет обновляться, в данный момент используется Thread.sleep.. это будет намного лучше:)

Вот мой код:

package beckyOwnProjects;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}

Ответ 10

Неявная ожидание: во время неявного ожидания, если веб-драйвер не сможет найти его немедленно из-за его доступности, WebDriver будет ждать указанного времени, и он не попытается найти элемент снова в течение указанного периода времени. Как только указанное время закончится, он попытается снова выполнить поиск элемента в последний раз перед тем, как выбросить исключение. Значение по умолчанию равно нулю. Как только мы установим время, веб-драйвер ждет период экземпляра объекта WebDriver.

Явная ожидание: может быть экземпляр, когда конкретный элемент занимает больше минуты, чтобы загрузить. В этом случае вам определенно не нравится устанавливать огромное время на Implicit wait, как если бы вы сделали это, ваш браузер будет ждать того же времени для каждого элемента. Чтобы избежать этой ситуации, вы можете просто выделить отдельное время только для требуемого элемента. Следуя этому, ваше молчаливое время ожидания браузера будет кратким для каждого элемента, и оно будет большим для определенного элемента.

Ответ 11

Иногда неявный wait терпит неудачу, заявляя, что элемент существует, но на самом деле этого не делает.

Решение состоит в том, чтобы избежать использования параметра driver.findElement и заменить его на нестандартный метод, который явно использует явно выраженный Wait. Например:

import org.openqa.selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

Есть дополнительные причины, чтобы избежать неявного ожидания, кроме спорадических, случайных сбоев (см. ссылку ).

Вы можете использовать этот метод "element" так же, как driver.findElement. Например:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

Если вы действительно хотите подождать несколько секунд для устранения неполадок или какого-либо другого редкого случая, вы можете создать метод паузы, аналогичный тому, что предлагает IDE селена:

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Ответ 12

Ответ: подождите несколько секунд, прежде чем видимость элемента с помощью Selenium WebDriver пройдет ниже методов.

implicitlyWait(): экземпляр WebDriver ожидает полной загрузки страницы. Вам нужно использовать 30-60 секунд, чтобы дождаться загрузки полной страницы.

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

ExplicitlyWait WebDriverWait(): экземпляр WebDriver ожидает полной загрузки страницы.

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

Примечание. Для обработки любого конкретного WebElement используйте ExplicitlyWait WebDriverWait().

Ответ 13

Я предпочитаю следующий код ждать 2 секунды.

for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
   Thread.sleep(1000);
}

Ответ 14

Thread.sleep(1000);

хуже: быть статическим ожиданием, это сделает тестовый скрипт медленнее.

driver.manage().timeouts.implicitlyWait(10,TimeUnit.SECONDS);

это динамическое ожидание

  • он действителен до существования webdriver или имеет область действия до срока службы драйвера
  • мы также можем подразумевать ожидание.

Наконец, я предлагаю

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);

с некоторыми предопределенными условиями:

isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
  • Это также динамическое ожидание
  • в этом ожидание будет только в секундах
  • мы должны использовать явное ожидание определенного веб-элемента, который мы хотим использовать.

Ответ 15

public static void waitForElement(WebDriver driver)throws Exception {
        driver.findElement(By.xpath("//table")).sendKeys //line1(org.openqa.selenium.Keys.CONTROL);
        Thread.sleep(500);
}

Используйте этот код, если страница обновляется, когда вы меняете элемент управления из одного поля ввода в другое поле ввода на той же странице. Передайте соответствующую ссылку драйвера этому методу, чтобы найти элемент. Строка1 используется для перехода на другую сторону, что делает обновление. Если у вас есть какие-либо вопросы, отправьте свой комментарий.