Selenium - Ожидание сетевого трафика - PullRequest
16 голосов
/ 06 ноября 2010

Мы используем Selenium с Java API и некоторыми пользовательскими расширениями Javascript. Мы используем много вызовов AJAX в нашем приложении. Многие наши тесты случайно не выполняются, потому что иногда вызовы AJAX заканчиваются медленнее, чем в других случаях, поэтому страница загружается не полностью. Мы исправляем это, ожидая определенных элементов или Thread.sleep. Я пытался найти способ вместо этого просто дождаться окончания сетевого трафика. Чтобы мы могли сделать это:

selenium.click("some JS button");
selenium.waitForNetwork();
assertTrue(something);

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

Мне не удалось найти способ выполнить поиск в Google. У кого-нибудь есть идеи, как этого добиться? (Желательно либо через Javascript, либо через Java API, но все предложения приветствуются).

Примечание: другие варианты "waitFor" - не то, что я ищу. Мы уже используем их в кликах и других вещах. Я ищу что-то, что ждет сетевой трафик. Спасибо за все отзывы, я опробую несколько предложений, но я все еще открыт для других идей.

Спасибо.

Ответы [ 6 ]

4 голосов
/ 06 ноября 2010

Попробовав все варианты, описанные на этой странице, мы получили следующую стратегию:

Внедрить специальный javascript, который в основном переопределяет все ваши соответствующие методы инфраструктуры и сохраняет счетчик числа незавершенных запросов, который увеличивается при запуске и уменьшается при завершении. Из-за асинхронной природы javascript не достаточно для сохранения логической переменной, вы, скорее всего, столкнетесь с условиями гонки в своей собственной логике.

Если вы используете визуальные эффекты, возможно, вы захотите сделать это и для визуальных эффектов; морфинг / выцветание и другие визуальные эффекты будут иметь ту же проблему.

Таким образом, мы в основном делаем обычный «щелчок» и затем всегда ждем, пока этот счетчик снова не достигнет 0, используя javascript так же, как другие предлагают здесь. После того, как мы это сделали, мы сократили временные проблемы до нуля.

Помните, что селен не возвращается из «щелчка» до тех пор, пока не будут обработаны все синхронные события onclick, поэтому вы должны убедиться, что эти счетчики увеличиваются как прямое следствие onclick.

Для получения инструкций о том, как переопределить методы фреймворка, вам следует обратиться к документации по фреймворку; мы используем addMethods в прототипе. Это переопределение можно сохранить в специальном JavaScript, который добавляется на страницу только при запуске тестов.

4 голосов
/ 06 ноября 2010

Существует несколько типов ожидания для Selenium. В вашем тестовом случае, если вы знаете, что при загрузке страницы появится определенный текст, вы можете использовать waitForText. Если заполняются различные элементы DOM (через Ajax / pageload), вы можете последовательно добавить waitForText.

2 голосов
/ 20 ноября 2010

Обновление: я использую тот же метод (wrapRequest) таким же образом с Selenium2, и он все еще работает.Разница лишь в том, что я не использую расширение пользователя.Я просто выполняю javascript для запроса кода, который загружен JSP.

Вот что мы в итоге сделали.(Обратите внимание, что есть более простые способы получить, если Ajax-вызов выполняется, если вы всегда используете только один фреймворк, такой как JQuery. Нам пришлось немного подстроить это, потому что у нас есть несколько страниц, использующих JQuery, и множествоиспользуйте GWT)

Я создал файл Javascript, который загружается на каждой странице, только если вы тестируете.(Я сделал это, включив фрагмент в шаблон нашего JSP: если параметр строки запроса тестирования передается как true, установите cookie. Если этот cookie установлен, включите файл javascript) Этот файл javascript по существу оборачивает объект XMLHttpRequest, чтобы вести подсчетиз всех запросов на отправку:

function wrapRequest(xmlRequest) {
    var oldSend = xmlRequest.prototype.send;
    xmlRequest.prototype.send = function() {
        var oldOnReady = this.onreadystatechange;
        oldOnReady = function() {
            oldOnReady.apply(this, arguments);
            // if call is complete, decrement counter.
        }
        // increment counter
        if(oldSend.apply)
            oldSend.apply(this, arguments);
        else if (oldOnReady.handleEvent) { //Firefox sometimes will need this
            oldOnReady.handleEvent.apply(this, arguments);
        }
    }
}

Это немного больше, чем это, если async == false, но это должно быть достаточно легко выяснить.

Затем я добавил функциюв файл selenium user-extensions.js, который выглядит просто так:

Selenium.prototype.getIsNetworkReady = function() {
    if(this.browserbot.topWindow.isNetworkReady) { //sometimes this method is called before the page has loaded the isNetworkReady function
        return this.browserbot.topWindow.isNetworkReady();
    }
    return false;
}

Также обратите внимание на проверку topWindow: это связано с тем, что при выборе iframe возникают проблемы.

Такжевам придется вызывать метод wrapRequest для объекта XMLHttpRequest каждого загружаемого iFrame.Я делаю это прямо сейчас, используя: document.addEventListener("DOMNodeInserted", onElementAdded, true);, а затем в onElementAdded я просто беру iframe, когда он загружается, и передаю объект XMLHttpRequest.но это не работает в IE, поэтому я ищу альтернативу.Если кто-нибудь знает лучший способ сделать это так, чтобы он работал как в IE, так и в FF, я бы хотел услышать это.

В любом случае, это суть реализации.Надеюсь, это поможет кому-нибудь в будущем.

1 голос
/ 10 ноября 2010

Это может быть неприемлемо для вас, но из-за подобных проблем мы перешли на Selenium 2 (он же WebDriver). Мы используем PageFactory с AjaxElementLocatorFactory

Чтобы упростить миграцию, существует Selenium Emulation , и планируется полностью объединить Selenium 1 и WebDriver, что является главной целью Selenium 2.

1 голос
/ 06 ноября 2010

У нас уже есть код на стороне клиента для изменения курсора мыши во время AJAX-запроса (используется a4j:status с атрибутами onstart и onstop). Поэтому мы можем просто подождать значение выражения JavaScript

window.document.body.style.cursor

Однако я обнаружил, что это не работает надежно, т. Е. Иногда тест проходит слишком рано. Я не уверен в причине, но подозреваю, что обновление DOM не обязательно полностью выполняется при вызове onstop.

Что касается сокращения ненужной задержки, вы можете проводить опрос самостоятельно и опрашивать чаще, чем селен.

0 голосов
/ 06 ноября 2010

Да, сделайте что-то вроде этого (псевдокод):

int i = 0;
while (element is not yet present) {
  i++;
  if (i>TRESHOLD) {
    throw an exception
  }
  Thread.sleep(200);
}
//go on

Вы, вероятно, хотите вставить это в функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...