Я надеюсь, что это только я, но Selenium Webdriver кажется полным кошмаром. В настоящее время веб-драйвер Chrome непригоден для использования, а другие драйверы весьма ненадежны, или, похоже, так оно и есть. Я борюсь со многими проблемами, но вот одна.
Случайно мои тесты не пройдут с
"org.openqa.selenium.StaleElementReferenceException: Element is no longer attached
to the DOM
System info: os.name: 'Windows 7', os.arch: 'amd64',
os.version: '6.1', java.version: '1.6.0_23'"
Я использую вебдрайвер версии 2.0b3. Я видел это с драйверами FF и IE. Единственный способ предотвратить это - добавить фактический вызов Thread.sleep
до возникновения исключения. Это плохой обходной путь, поэтому я надеюсь, что кто-то может указать на ошибку с моей стороны, которая сделает все это лучше.
java
selenium-webdriver
webdriver
automated-tests
Рэй Николус
источник
источник
from selenium.common.exceptions import NoSuchElementException
Ответы:
Да, если у вас есть проблемы с StaleElementReferenceExceptions, это потому, что ваши тесты плохо написаны. Это состояние гонки. Рассмотрим следующий сценарий:
Теперь в точке, где вы щелкаете элемент, ссылка на элемент больше не действительна. Для WebDriver практически невозможно догадаться обо всех случаях, когда это может произойти - поэтому он вскидывает руки и дает вам контроль, кто как автор теста / приложения должен точно знать, что может или не может произойти. Что вы хотите сделать, так это явно подождать, пока DOM не окажется в состоянии, когда вы знаете, что все не изменится. Например, используя WebDriverWait для ожидания существования определенного элемента:
МетодsenceOfElementLocated () будет выглядеть примерно так:
Вы совершенно правы в том, что текущий драйвер Chrome довольно нестабилен, и вы будете рады услышать, что в стволе Selenium есть переписанный драйвер Chrome, где большая часть реализации была сделана разработчиками Chromium как часть их дерева.
PS. В качестве альтернативы, вместо явного ожидания, как в примере выше, вы можете включить неявное ожидание - таким образом WebDriver всегда будет зацикливаться до указанного времени ожидания в ожидании появления элемента:
Однако, по моему опыту, явное ожидание всегда более надежно.
источник
com.google.common.base.Function<F, T>
предоставлено Guava .Я смог использовать такой метод с некоторым успехом:
Да, он просто продолжает опрашивать элемент, пока он больше не считается устаревшим (свежим?). На самом деле не доходит до корня проблемы, но я обнаружил, что WebDriver может быть довольно требователен к выбрасыванию этого исключения - иногда я получаю его, а иногда нет. Или это может быть, что DOM действительно меняется.
Поэтому я не совсем согласен с ответом выше, что это обязательно указывает на плохо написанный тест. У меня это на свежих страницах, с которыми я никак не взаимодействовал. Я думаю, что в том, как DOM представлен, или в том, что WebDriver считает устаревшим, есть некоторая слабость.
источник
Иногда я получаю эту ошибку, когда обновления AJAX находятся на полпути. Похоже, что Capybara достаточно умен в ожидании изменений DOM (см. Почему wait_until был удален из Capybara ), но время ожидания по умолчанию в 2 секунды было просто недостаточно в моем случае. Изменено в _spec_helper.rb_ с помощью например
источник
Сегодня я столкнулся с той же проблемой и создал класс-оболочку, который перед каждым методом проверяет, является ли ссылка на элемент все еще действительной. Мое решение получить элемент довольно просто, поэтому я решил поделиться им.
Вы видите, что я «найду» или, скорее, сохраню элемент в глобальной переменной js и получу элемент, если это необходимо. Если страница будет перезагружена, эта ссылка больше не будет работать. Но до тех пор, пока вносятся только изменения, ссылка остается. И это должно делать работу в большинстве случаев.
Также это позволяет избежать повторного поиска элемента.
Джон
источник
У меня была та же проблема, и моя была вызвана старой версией селена. Я не могу обновиться до более новой версии из-за среды разработки. Проблема вызвана HTMLUnitWebElement.switchFocusToThisIfNeeded (). При переходе на новую страницу может случиться так, что элемент, который вы щелкнули на старой странице, - это
oldActiveElement
(см. Ниже). Selenium пытается получить контекст от старого элемента и терпит неудачу. Вот почему они создали попытку поймать в будущих выпусках.Код из версии selenium-htmlunit-driver <2.23.0:
Код из версии selenium-htmlunit-driver> = 2.23.0:
Без обновления до 2.23.0 или новее вы можете просто указать любой элемент на странице. Я просто использовал,
element.click()
например.источник
Это случилось со мной, когда я пытался отправить send_keys в поле ввода поиска - в нем есть автообновление в зависимости от того, что вы вводите. Как упоминалось в Eero, это может произойти, если ваш элемент обновляет Ajax, когда вы вводите свой текст внутри элемента ввода , Решение состоит в том, чтобы посылать по одному символу за раз и снова искать элемент ввода . (Например, в рубине показано ниже)
источник
Чтобы добавить к ответу @ jarib, я сделал несколько методов расширения, которые помогают устранить состояние гонки.
Вот моя установка:
У меня есть класс под названием «Driver.cs». Он содержит статический класс, полный методов расширения для драйвера и других полезных статических функций.
Для элементов, которые мне обычно нужно получить, я создаю метод расширения, подобный следующему:
Это позволяет вам извлечь этот элемент из любого тестового класса с помощью кода:
Теперь, если это приводит к
StaleElementReferenceException
, у меня есть следующий статический метод в моем классе драйвера:Первым параметром этой функции является любая функция, которая возвращает объект IWebElement. Второй параметр - это время ожидания в секундах (код для времени ожидания был скопирован из Selenium IDE для FireFox). Код можно использовать для исключения исключения устаревшего элемента следующим образом:
Вышеприведенный код будет вызываться
driver.SpecificElementToGet().Displayed
до тех пор, пока неdriver.SpecificElementToGet()
сгенерирует никаких исключений и не.Displayed
оценит их доtrue
5 секунд. Через 5 секунд тест не пройден.С другой стороны, чтобы дождаться отсутствия элемента, вы можете использовать следующую функцию таким же образом:
источник
Я думаю, что нашел удобный подход для обработки исключения StaleElementReferenceException. Обычно вам нужно написать оболочки для каждого метода WebElement, чтобы повторить действия, что разочаровывает и тратит много времени.
Добавление этого кода
перед каждым действием WebElement можно повысить стабильность ваших тестов, но вы все равно можете время от времени получать исключение StaleElementReferenceException.
Так вот что я придумал (используя AspectJ):
Чтобы включить этот аспект, создайте файл
src\main\resources\META-INF\aop-ajc.xml
и напишитеДобавьте это к вашему
pom.xml
И это все. Надеюсь, поможет.
источник
Вы можете решить эту проблему с помощью явного ожидания, так что вам не придется использовать сложное ожидание.
Если вы выбираете все элементы с одним свойством и просматриваете его, используя для каждого цикла, вы можете использовать ожидание внутри цикла следующим образом:
или для одного элемента вы можете использовать приведенный ниже код,
источник
В Java 8 вы можете использовать очень простой метод для этого:
источник
источник