Для поддержки ожидания AJAX-запросов на страницах Thucydides предоставляет множество удобных методов ожиданий, а также стандартный механизм PageObject, реализованный на основании использования
AjaxElementLocatorFactory
(про реализацию PageObject для работы с AJAX можно почитать в этой статье).
Но обо всем по порядку, сперва рассмотрим как реализовано использование фабрик в Thucydides.
DisplayedElementLocatorFactory
По умолчанию фреймворк использует DisplayedElementLocatorFactory
и DisplayedElementLocator
, которые унаследованы от AjaxElementLocatorFactory
и AjaxElementLocator
соответственно, и по своей функциональности практически им идентичны, за исключением небольших изменений, о которых я расскажу ниже.
Для начала посмотрим как мы можем использовать эти фабрики на своих тестовых страницах. PageObject для инициализации предоставляет два варианта конструктора:
public PageObject(final WebDriver driver, final int ajaxTimeout) {
public PageObject(final WebDriver driver) {
На самом деле оба конструктора реализуют поддержку ajax, просто первый позволяет задавать таймаут для каждой отдельной страницы, а второй использует общее значение для всех страниц (свойство thucydides.timeout
, по умолчанию равно 5 секундам). Первый вариант конструктора никогда не вызывается в Thucydides явно. Во время инициализации страниц средствами фреймворка всегда запрашивается конструктор второго типа. Поэтому вызов первого конструктора на дочерних страницах мы должны выполнить самостоятельно. Параметр ajaxTimeout позволяет задать в миллисекундах время ожидания появления элемента на странице, но не менее 1 секунды (значение меньше 1000 миллисекунд автоматически приравнивается к 1 секунде).
public class CatalogFilterPage extends PageObject { /** * 10 секунд */ private static final Integer CATALOG_WAIT_FOR_TIMEOUT = 10000; @FindBy(id = "search") WebElement searchButton; public CatalogFilterPage(WebDriver driver) { super(driver, CATALOG_WAIT_FOR_TIMEOUT); } public boolean searchButtonIsVisible() { return element(searchButton).isVisible(); } }
Теперь при любом обращении к элементу, будь то нажатие или получение свойств, будет автоматически выполняться ожидание появления элемента на странице заданный промежуток времени. Но что если мы хотим узнать сразу виден этот элемент или нет, а не дожидаться истечения таймаута. Для этого Thucydides предоставляет ряд методов, которые возвращают результат мгновенно: isCurrentlyVisible, isCurrentlyEnabled, shouldNotBeVisible
.
public boolean searchButtonIsVisibleNow() { return element(searchButton).isCurrentlyVisible(); }
Мгновенное выполнение таких методов относится к первому отличию DisplayedElementLocator
от AjaxElementLocator
.
Второе отличие заключается в механизме ожидания элемента, если AjaxElementLocator
дожидается просто появления элемента на странице, то DisplayedElementLocator
ждет пока элемент будет присутствовать и станет видимым. Это очень важная черта поведения, в случае если фабричный элемент присутствует, но не видим, Thucydides никогда его не получит.
Что делать, если нужно работать со скрытыми элементами?
Использовать стандартную фабрику AjaxElementLocatorFactory
или DefaultElementLocatorFactory
(если AJAX не нужен вовсе). Но смену фабрики можно выполнить только в Thucydides версии выше 0.9.88. Задается фабрика с помощью свойства thucydides.locator.factory
:
-Dthucydides.locator.factory=AjaxElementLocatorFactory
Как я уже говорила выше, по умолчанию используется DisplayedElementLocatorFactory
. Не забывайте, что изменяя фабрику Вы теряете некоторую функциональность, в частности использование методов current.
Методы wait
Дожидаться появления элементов можно не только с помощью фабрики. Thucydides предоставляет ряд удобных методов для ожидания появления элементов, их исчезновения или смены свойств. Эти методы реализованы как в классе PageObject
, так и в классе WebElementFacade
. Все методы ожиданий начинаются с приставки wait
:
waitForPresenceOf(".//*[@class='indicator']");
element(webElement).waitUntilDisabled();
Какой таймаут выдерживают такие ожидания? При передаче в конструктор страницы параметра ajaxTimeout
время ожидания в методах также устанавливается в значение ajaxTimeout, при использовании второго варианта конструктора время по-умолчанию будет равно 30-ти секундам.
И напоследок, аналог всеми любимого Thread.sleep(5000)
. Если очень хочется использовать явную приостановку выполнения на странице, в Thucydides есть для этого метод waitABit(5000);
в классе PageObject
.
Здравствуйте,
Можно ли каким-нибудь образом задать свою фабрику? По исходникам вроде как нельзя, но может есть какой обходной путь?
Нужно это для кастомного @FindBy, который будет инициализировать элементы, выгребая локаторы в зависимости от настроек из конфигов.
Сам и отвечу 🙂 Со 106й версии можно переопределить PageObject и внутри переопределенного конструктора можно вызвать кастомную фабрику.
Больше по ссылке https://github.com/thucydides-webtests/thucydides/pull/66
Даже и не знал о популярности Thucydides на родине 🙂
В версии 0.9.111 я добавил SmartElementLocatorFactory — и это default factory.
Теперь можно создавать свои елементы (наследуюя их от WebElementFacadeImpl) и использовать @FindBy(jquery = «») и @FindBy(sclocator = «»). Последний используется для фреймворка SmartGWT.
Спасибо, хорошая серия. Недавно попробывала использовать JBehave + Thucydides, сгенирировала соответствующий Maven-проект (пример с Wiki) и столкнулась со следующей проблемой:
как указать что определенная story должна обрабатываться определенным step-классом. Этот класс должен содержать методы для обработки Given-, When-, Then-шагов, а также методы BeforeStory, AfterStory, BeforeScenario, AfterScenario, выполняемые только для этой одной конкретной story?