it-roy-ru.com

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

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

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

а также

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

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

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

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

91
Prince

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

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 определяет максимум количество времени ожидания условия, а также частота, с которой проверяется условие. Кроме того, пользователь может настроить время ожидания для игнорирования определенных типов исключений во время ожидания, таких как NoSuchElementExceptions, при поиске элемента на странице. Подробности вы можете получить здесь

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

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

Такой подход ИМХО лучше, так как вы не знаете точно, сколько времени ждать, а в интервале опроса вы можете установить произвольное значение времени, наличие которого будет проверяться с помощью…. Regards.

110
eugene.polschikov

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

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

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

16
Anup

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

Хотя я все еще сталкиваюсь с ситуациями, когда система находится под большой нагрузкой, и когда я нажимаю кнопку отправки (например, 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;
}

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

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

/**
 * 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

11
Jeff Vincent

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

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

8
Valentin

Мне нравится использовать пользовательские условия. Вот некоторый код на 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 возвращает список - пусто или нет, нужно просто проверить.

3
simno

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

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

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

2
Dion
Thread.Sleep(5000);

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

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

OR

Добавить объявление бросков:

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

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

1
Prasad Hajare

Иногда неявное ожидание терпит неудачу, говоря, что элемент существует, но это действительно не так.

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

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();

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

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

Неявное ожидание и 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();
    }

}
0
Beckham Vinoth

Иногда неявное ожидание переопределяется, и время ожидания сокращается. У [@ eugene.polschikov] была хорошая документация о причинах. Я обнаружил в своем тестировании и кодировании с Selenium 2, что неявное ожидание - это хорошо, но иногда вам приходится ждать явно. 

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

0
BadgerAndK

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

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

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

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

WebDriverWait wait = new WebDriverWait(driver, 60);

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

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

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

0
sandeep shewale

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

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

0
Abhishek Singh