Использую selenide + java.
Нужен совет (бестпрактис), как реализовать ожидание элемента с результатом boolean в селениде?
текущий вариант
- implicitlyWait(2000)
- exists()
- implicitlyWait(0)
Может есть более красивое решение?
Использую selenide + java.
Нужен совет (бестпрактис), как реализовать ожидание элемента с результатом boolean в селениде?
текущий вариант
Может есть более красивое решение?
не знаю как в селениде но на чистом селениуме
implicitly 0
explicitylywait for exists 2000
implicitly default
Это какой-то ахтунг…
Что вам вообще надо? Что вы хотит сделать? Какую проблему решаете?
Вот так надо написать, и никаких ожиданий не надо прописывать:
$("div").should(exist);
Да, сомнительно, по этому и тема создана.
Бывает что нужно проверить есть ли элемент, который появляется с задержкой. Только в случае отсутствия элемента возвращается false, а не эксепшен(not found).
Например информационное окно, которое не влияет на логику, но блокирует выполнение. Если оно появилось, то его нужно закрыть. Что то типо verify.
трай кетч пробовали?
try {
wait for element
return true
}
catch(NotFoudnException e){
return false;
}
угу, но селенид поймает исключение первым и тест завершится, т.е завершится на шаге wait for element.
Для селениума красивое решение(ваш вариант), есть еще вариант через коллекцию элементов, если кол-во равно нулю, то элемента нет.
Просто у селенида методы проверки состояния элемента сделаны через (assert) и при NotFoudnException тест завершает…
Это невозможно, гуглите про стек вызовов
Вот так никуда эксепшн не улетит:
public boolean isVisible() {
try {
$("div").should(exist);
return true
} catch (error) {
return false
}
}
Давайте разберем на примере
public boolean isVisible() {
try {
$("div").should(exist);
return true
} catch (error) {
return false
}
}
Если элемент не найден в строке “$(“div”).should(exist);” то по истечении 4х секунд, тест завершиться ошибкой элемент не найден. Т.е. мы не попадем в блок catch, так как тест дальше не выполняется.
Разве не так?
.shoud бросает исключение про прошествии 4 секунд.
Мы ловим это исключение и останавливаем движение эксепшена по стеку. А вместо делаем обычный (не аварийный) выход из функции
https://en.wikibooks.org/wiki/Java_Programming/Throwing_and_Catching_Exceptions
Насколько я разобрался в selenide то метод $(getElemet) где то дальше вызывает метод
public Object invoke(Object proxy, Method method, Object... args)
где proxy уже содержит исключение, а дальше в теле метода идет обработка этого исключения.
т.е. в примере isVisible исключение уже отловлено и обработано в методе $. и как бы тест завершен уже…)
Разве не так?
Если кто знает как через селенид красиво определять существует ли элемент, только что бы проверка была не ключевая, а информационная и не влияла на ход теста. [quote=“asolntsev, post:3, topic:19650, full:true”]
$(“div”).should(exist);
[/quote]
В данном случае, если элемента нет, то тест будет завершен, а нужно что бы продолжился…
старался понятно объяснить, если что сорян
Любопытная тема обсуждается
Тоже поделюсь, как это обычно делаю, поскольку приходилось с ожиданиями работать.
Только селениум здесь не причем, вопрос ожиданий более общий.
Да и в целом не использую ожидания селениума, ввиду их негибкости.
Делаю в модуле utils
пару функций:
waitFor
- принимает функцию и время ожидания, возвращает true
если функция вернула truly
в течение таймаута, false
если таймаут истек, a функция так и не вернула truly
;waitDuring
- принимает функцию и время ожидания, возвращает true
если функция постоянно возвращает truly
в течение таймаута, false
если в течение таймата был возвращен falsy
, используется гораздо реже.А для селениум-объектов создаются методы:
isExist
- возвращает true
если объект существует в виде DOM
-объекта (но может быть и не видимый), false
если не существует.isVisible
- возвращает true
если объект существует и видимый на экране (полностью или частично - можно указать в виде параметра функции), false
если не существует или не видимый.waitForExist = function (timeout=30) {
var result = utils.waitFor(() => this.isExist(), timeout);
if (!result) {
throw new Error(`Element ${this.selector} doesn't exist after ${timeout}`);
}
}
waitForNonExist = function (timeout=30) {
var result = utils.waitFor(() => !this.isExist(), timeout);
if (!result) {
throw new Error(`Element ${this.selector} still exists after ${timeout}`);
}
}
waitForVisible = function (timeout=30) {
var result = utils.waitFor(() => this.isVisible(), timeout);
if (!result) {
throw new Error(`Element ${this.selector} isn't visible after ${timeout}`);
}
}
waitForInvisible = function (timeout=30) {
var result = utils.waitFor(() => !this.isVisible(), timeout);
if (!result) {
throw new Error(`Element ${this.selector} is still visible after ${timeout}`);
}
}
Тогда если нужно подождать появления или бросить исключение, то используется функция waitForVisible
.
А если более низкоуровневое типа подождать и вернуть true/false
то utils.waitFor(() => element.isVisible(), /* timeout */ 30)
Ну и конечно есть свой матчер waitFor
для chaijs
, н-р так:
expect(() => page.table.getRows()).to.waitFor({ "be equal": 5 });
Вот в этом весть ахтунг!
Так чего же вы вообще хотите?
Зачем вообще тогда проверять элемент, если тест в обоих случаях продолжается?
В моем случае это информационное окно, которое появляется из за определенных параметров. Например сообщение “у вас новое письмо” с кнопкой “ок”.
Я понимаю вашу логику, я пытался найти возможность что бы перед началом теста отключить появление этого окна или точно включить, что бы исключить условно случайное появление окна. Но это невозможно, по этому нужна проверка, если есть окно то жмем ок и продолжаем тест, если нет, то продолжаем тест…
Какой софт, такие тесты Видимо компания “Ломаем моторы” решила, что хватит делать ручное тестирование, пора внедрять трендовую автоматизацию, но вот не учли, что автоматизация магически сбоку не прилипнет, и нужно менять процессы. А то так и будут тесты на костылях.
Вангую что отображение этого окна зашито в куках, надо же как-то хранить инфу отображалось оно или нет, что бы на каждой странице не выскакивало. Так что проствляйте эту куку перед запуском.
Конечно же, это возможно. Не верите мне - поверьте Билану.
Но ок, если предположить, что невозможно, то вот такой код закроет окно, если оно открылось:
if ($("#info").isDisplayed()) {
$("#info-close").click();
}
Как видите, тут не нужны никакие ожидания.
Может я что то не догоняю, но какой то бег по кругу…
окно появляется с задержкой
$("#info").isDisplayed()
- метод без задержки. Очевидно что будут ситуации когда окно будет появляться позже отработки метода isDisplay(). Это будет работать если перед if поставить ожидание - sleep ()… Но суть темы, в том что бы не было этого.
…
Может вот так попробовать:
if ($("#info").waitUntil(visible, 4000).isDisplayed()) {
$("#info-close").click();
}
Да, это бег по кругу, потому что тут нет хорошего решения. Если окно может появиться с задержкой, вы просто обязаны сделать sleep, причём максимально возможный. И это в любом случае будет плохо. Нет никакой магии, которая решила бы эту проблему за вас.
Единственное правильное решение - это взять тестовую среду под свой контроль. Вы сами должны указывать, когда окошко должно появляться, а когда не должно.
Два чаю этому господину. Я бы тоже разобрался с приложением вместо разбирательств с тестами.