StaleElementReferenceException — одно из самых интригующих исключений, какое вы могли встретить, тестируя с помощью Selenium. Надеюсь, что этот пост поможет вам решить проблему с появлением данного исключения в ваших тестах.

Что такое StaleElementReferenceException?

Согласно документации Selenium Webdriver, слово “stale” означает то, что ссылка на элемент теперь “несвежая” — элемент больше не появляется в DOM страницы. Проще говоря, элемент, который вы обнаружили с помощью метода findElement, исчез, когда вы инициировали взаимодействие с ним.

Давайте разберем некоторые аспекты того, как Selenium WebDriver обрабатывает этот сценарий.

Внутреннее устройство WebDriver

Когда вы пишете синтаксис для выполнения какого-либо действия с помощью Selenium WebDriver, он обращается внутренним вызовом к API WebDriver, связанному с этим методом.

Принцип работы Selenium WebDriver

Метод WebDriver

Например, если вы ищете способ найти элемент в браузере, используя Selenium WebDriver и Java, синтаксис будет выглядеть следующим образом:

Поиск элемента с использованием Id в качестве селектора

Запрос к API

Теперь метод Java внутренне вызывает API WebDriver POST-запросом через передачу информации о локаторе в теле запроса, как показано ниже:

Запрос FindElement, отправленный через Postman

В приведенном выше запросе localhost указывает на chromedriver, работающий в качестве локального сервера на порте 9515.

Примечание: при запуске тестов из IDE (такой как Eclipse), Selenium находит свободный порт во время выполнения, и это может быть не 9515, который является портом по умолчанию.

Ответ API

Ответ API от сервера chromedriver при успешном нахождении соответствия вернет WebElement и будет выглядеть следующим образом:

Ответ с информацией об элементе

Здесь вы найдете информацию об элементе с уникальным идентификатором для каждой сессии и запрошенного DOM. Примечание: информация об элементе изменится, когда страница будет перезагружена или если к ней будет совершен переход из других сессий.

Информация об элементе после перезагрузки

Ответ WebDriver

Эта информация об элементе принимается в качестве ответа от метода findElement в WebDriver и преобразуется к типу WebElement.

Ответ API преобразован в WebElement

Browser Driver выбрасывает исключение о несвежей ссылке на элемент

С учетом данной информации становится очевидным, что при попытке взаимодействовать с элементом, найденным несколькими миллисекундами раньше, он мог исчезнуть, потому что страница оказалась обновлена/перезагружена при взаимодействии с ней кликом, тапом или как-то иначе.

Из-за этого изменения информации об элементе в DOM между вызовами (locate и action) ChromeDriver (а не Selenium WebDriver), выбрасывает исключение о несвежей ссылке на элемент (Stale Element exception). 

Stale Element Exception от Chrome Driver

Подводя итог: исключение создается ChromeDriver (а не Selenium WebDriver), когда информация об элементе оказывается изменена при перезагрузке страницы между locate (findElement) и action (click/sendKeys).

Как мы можем справиться с этим исключением?

Существует несколько способов. Вам стоит подобрать самый простой и оптимальный вариант, основанный на характере возникающей у вас проблемы и вашем опыте.

  1. Просто подождите

Добавьте простое ожидание, используя Thread.sleep, на несколько секунд (или, может быть, немного больше, в зависимости от времени, за которое, по вашему мнению, ваше приложение сможет завершить компонент), прежде чем искать элемент с помощью findElement. 

2. При появлении исключения возвратитесь к поиску элемента

Добавьте обработку исключений к своему действию, и если появится исключение Stale Element, то повторите попытку найти (locate) элемент после простого ожидания в течение 500 миллисекунд. Повторяйте эти действия до тех пор, пока действие не завершится успешно или не будет выполнено максимально допустимое количество итераций.

3. Используйте инструменты разработчика, чтобы знать состояние DOM

Используйте API dev-tools для того, чтобы узнавать, был ли DOM перезагружен между findElement и щелчком мыши. Если DOM оказался обновлен, то запросите у слушателя новую информацию об элементе для следующего действия.

По ссылке на GitHub вы найдете больше подробностей.

Заключение

Исключения StaleElementReferenceException — одни из распространенных, и как только вы узнаете, почему они появляются и как с ними справляться, вы их одолеете. Каждое исключение научит вас чему-то уникальному, так что продолжайте учиться.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Babu Manickam: The Untold Story — Stale Element Reference Exception in Selenium

Предыдущая статьяНовый взгляд на старые истины: принцип «Не повторяйся!» (DRY)
Следующая статьяDeepnote - новая IDE для специалистов по данным