Всем привет! Данная ошибка является очень популярной при использовании Selenide автотестах в Java. На поиск решения у меня ушло довольно много времени, поэтому в этой статье я хочу подробно рассказать про эту ошибку и как с ней работать.

Что такое Stale Element Reference и как ее избежать

Stale Element Reference (дальше буду писать SER) является исключением, при котором элемент на странице меняет свой айди при изменении DOM дерева. Чаще всего эту ошибку можно поймать при переборе коллекции элементов в Selenide.

Что я понял про ошибку SER?

В Selenide при итерации списка выполняется метод .snapshot() который замораживает эту коллекцию и элементы стают неизменны, а путь элемента на странице остается прежним. Соответственно мы не сможем обратиться к обновленному элементу, если изменится DOM дерево страницы.

Есть сайт специально для отлова ошибок и тренировки поиска элементов через Xpath. Как раз на этом сайте можно можно поймать SER

Сайт - http://the-internet.herokuapp.com/challenging_dom

Давайте определим коллекцию элементов (3 разноцветные кнопки, которые находятся слева).

ElementsCollection buttons = $$x(".//a[contains(@class,'button')]");

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

Например вот так, мы словим SER перед нажатием на вторую кнопку.

for (SelenideElement button : buttons){
            button.click();
        }

Коллекцию элементов можно обновить только через получение какого то элемента из нее, вызвав метод .get(index), соответственно коллекция обновляется и пути к элементам тоже обновляются, а ошибка SER не вылазит.

Можно перебирать элементы таким способом:

for(int i = 0; i<buttons.size(); i++){
            buttons.get(i).click();
        }

Как вариант можно использовать цикл forEach, добавив в него внешний индекс. Также ошибки SER не будет.

int index = 0;
        for (SelenideElement button : buttons){
            buttons.get(index).click();
            index++;
        }

Также можно написать метод, который ловит SER ошибку и код программы продолжает выполняться.

public boolean isVisible(SelenideElement element) {
        try {
            return element.isDisplayed();
        }
        catch (StaleElementReferenceException e) {
            return false;
        }
    }

Также можно использовать этот простой цикл, чтобы перебрать коллекцию и добавить какое то условие максимально безопасно. То есть, если элемент будет SER, то будет переопределение элемента на странице и дальнейшее взаимодействие

int index = 0;
for (SelenideElement element : buttons) {
            if(isVisible(element)){
                element.click();
            } else {
                buttons.get(index).click();
            }
            index++;

После прочтения данной статьи многие автотестеры смогут решить свою проблему.

Комментарии (2)


  1. 3vi1_0n3
    17.08.2021 07:54

    А почему именно Selenide?
    В целом такая проблема возникает же не только при его испрользовании.
    Можно было бы добавить про чистый WebDriver, тогда это еще бОльшему количеству людей помогло. Тем более, что это достаточно актуально при тестировании тех же React приложений, которые сейчас достаточно популярны.


    1. asolntsev
      18.08.2021 01:03

      Юмор в том, что как раз с чистым вебдрайвером Stale Element Reference намного чаще возникает. А с Селенидом (почти) никогда. Кроме итерирования коллекции, но это само по себе плохая идея.