В этой статье мы рассмотрим тестирование WEB-приложений, использующих AJAX (т.е. при обновлении данных веб-страница не перезагружается полностью, изменяются лишь необходимые элементы). Автоматизация тестирования такого приложения ничем не отличается от автоматизации тестирования обычного WEB-приложения, за исключением того, что необходимо дожидаться выполнения AJAX-запроса. Например, если выполнение запроса добавляет элементы в DOM, то преждевременное обращение к таким элементам приведет к
NoSuchElementException
. Это происходит потому, что тест выполняется быстрее, чем сам AJAX-запрос.
Использовать Thread.sleep()
, устанавливающий ожидание истечения заданного времени, для решения этой проблемы очень не рекомендуется. По той простой причине, что нельзя заранее определить сколько времени может понадобиться на выполнение запроса, а если выделять время, так сказать, с запасом, то это приведет к тому, что тесты будут выполняться слишком долго (долго — это очень относительно, но точно дольше, чем могли бы).
Selenium 2 для таких случаев предоставляет возможность использовать явные и неявные ожидания.
Неявное ожидание указывает WebDriver опрашивать DOM в течение конкретного периода времени при поиске элементов, в случае если они не появились сразу. По умолчанию это значение равно 0. Если значение было однажды установлено, то оно будет использоваться перед выполнением каждой команды findElement
, ожидая элемент, на протяжении жизни экземпляра объекта WebDriver, либо пока не будет изменено.
WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Стоит обратить внимание на то, что метод findElements
ищет хотя бы один элемент удовлетворяющий условию поиска. И если такой элемент найден в момент обращения, то он возвращает его, не дожидаясь пока появятся остальные элементы.
Однако, имплицитные ожидания не позволяют дожидаться таких событий как, например, исчезновение элемента из DOM или смены свойств элемента. Для таких событий нужно использовать явные ожидания. Явные ожидания выполняются единожды, ожидая возникновения определенных условий в течение указанного периода времени. Для организации явных ожиданий Selenium предоставляет класс WebDriverWait
и интерфейс ExpectedCondition
.
WebDriver driver = new FirefoxDriver(); (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.getTitle().contains("MyTitle"); } });
В случае, если условие не было выполнено по истечении указанного времени, возращается TimeoutException
.
По умолчанию WebDriverWait
вызывает ExpectedCondition
каждые 500 миллисекунд до тех пор, пока условие не будет удовлетворено. Это значение можно изменить, установив свойство pollingEvery(sleepTimeOut, TimeUnit.MILLISECONDS)
или используя конструктор WebDriverWait(WebDriver driver,long timeOutInSeconds,long sleepInMillis)
, принимающий 3-им параметром длительность в миллисекундах между опросами. По умолчанию WebDriverWait
игнорирует NotFoundException, возникающее при вызове условия. Вы можете добавить больше исключений в список игнорирования, используя ignoring(Exception.class)
.
Следует также обратить внимание на класс ExpectedConditions, он предоставляет готовые условия ожидания. Вот некоторые из них:
stalenessOf(WebElement element)
— ожидание пока элемент исчезнет из DOM;titleIs(java.lang.String title)
— ожидание заголовка страницы;textToBePresentInElement(By locator, java.lang.String text)
— ожидание заданного текста в элементе;visibilityOfElementLocated(By locator)
— ожидание, что элемент присутствует в DOM и виден.
Полный список возможных условий можно посмотреть по этой ссылке.
Приведенный ранее пример можно переписать следующим образом, используя ExpectedConditions:
WebDriver driver = new FirefoxDriver(); (new WebDriverWait(driver, 10)) .until(ExpectedConditions.titleContains("MyTitle"));
Условия для проверки можно делать сколь угодно сложными, все зависит от конкретного случая и ситуации.
Спасибо! А я тут со Thread.sleep() мучился…
Огромное спасибо!
Татьяна как написать команду, жди пока страница полностью не загрузиться? ну как в selenium IDE «clickandwait «
Если речь идет о клике на ссылку или о команде
driver.get(URL)
, то ожидание происходит автоматически, т.е. если нажатие на элемент вызывает загрузку новой страницы, то этот метод будет блокировать дальнейшее выполнение, пока страница не загрузится. Но это относится только к загрузке самой страницы, отслеживание завершения AJAX запросов на ней нужно выполнять самостоятельно.