можно ли использовать явные и неявные ожидания вместе

Заполняю форму. При подстановке в поле ссылки она парсится и на это надо некоторое время. Далее мне надо нажать на кнопку. Но кнопка недоступна, пока парсится ссылка. И выдается соотвествующая ошибка и тест падает. У меня стоит implicity wait. Она как бы должна ждать пока кнопка будет кликабельна (я так думаю). Или лучше поставить explicit wait. Но слышал, что плохая практика использовать явные и неявные ожидания вместе. Я же не буду на каждый елемент ставить явное ожидание. Как лечше решить проблемму?

download

1 лайк

Я бы в данном случае использовал WebdriverWait. Сделал бы метод, который ожидал бы пока элемент станет Editable. Такой метод можно применять по мере необходимости, подставляя ему нужный элемент.

2 лайка

На сколько я знаю, нет ничего плохого в использовании явных и неявных ожиданий вместе.
Единственное надо понимать, чего ждет неявное ожидание. Неявное ожидание ждёт пока элемент появится на странице, когда Вы выполняете поиск элемента (FindBy). Оно не ждёт пока элемент станет редактируемым или кликабельным.

Для таких случаев используется явное ожидание. Во всех местах где Вам необходимо ждать чего-то другого, чем просто появление элемента на странице, Вам нужно будет прописывать явное ожидание.

Для таких случаев пишут отдельный метод/методы, который потом переиспользуют, где это необходимо.

3 лайка

Написал такой метод, но подсвечивает что не такой( что не так?

Без кода метода и сообщения, что именно подсвечивает, трудно что-то сказать

ИЗВИНИТЕ ))

public void explicitWait(ExpectedConditions expectedConditions){
WebDriverWait wait = new WebDriverWait(driver,20);
WebElement aboutMe;
aboutMe= wait.until(expectedConditions);
}

Где метод явного ожидания лучше объявлять, в пейдже или базовом классе?

В базовом классе пейджа

Мне кажется метод должен возвращать найденный/дожданный WebElement

Я думаю что метод просто выполняется, ждет элемент и все. Зачем ему что-то возвращать!?

Это было предположение. Тогда Вам смело можно убрать объявление локальной переменной aboutMe. И игнорировать результат выполнения метода until.

1 лайк

Лучше сделать этот метод по другому - чтобы он как параметр принимал WebElement, тогда он будет более универсальным и многоразовым.

1 лайк

public void explicitWait(WebElement element){
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.elementToBeClickable(element));
}

но выдает ошибку Element is not clickable at point (1458, 419). Other element would receive the click:

ВЕЙТ ДАЖЕ НЕ ЖДЕТ СВОЕГО ВРЕМЕНИ 20 СЕК, ТЕСТ СРАЗУ ПАДАЕТ!!!

А по-английски читать умеем? Чёрным по белому же написано, в чём проблема:

Element is not clickable at point (1458, 419). Other element would receive the click

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

Попробуйте в дебаге проверить свойства isEnabled и isDisplayed кнопки до вейта, во время вейта и после.

Внимательно смотрите (или спросите у разработчиков) не проскакивает ли там какой-то серый фон для дизейбла или другие элементы.

Ну как тут не ответить? :slight_smile:

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

$("input").setValue("http://your-link.com");
$("button").click();

И селенид сам уже дождётся, чтобы кнопка была кликабельная и всё такое.

По поводу явных и неявных ожиданий на SeleniumCamp 2018 был хороший доклад: seleniumcamp.com/talk/deep-dive-into-selenium-waits

Спойлер: и явные и неявные по-своему плохие. Используйте селенидовские.
Если вкратце — implicit wait умеет ждать только наступления одного события: что элемент появится в DOM. Селенидовские ожидания могут ждать чего угодно (например, что элемент исчезнет из DOM).

6 лайков

Не знаю насколько это правильно, но у себя я сделал несколько таких методов для разных лоадеров и вынес отдельный класс типа Ajax_loader.class и ставлю их в тесах там где знаю, что будет тот или иной спинер.

    public void waitForBlueSpinnerLoading() {
        $("div.k-waitForAjaxLoading-image").waitUntil(disappear, 120000);
    }

Потому что иногда данные долго из базы приходят. А так селенид использую)

1 лайк