Ошибка эталона устаревшего элемента в селене

Я получаю сообщение об ошибке при выполнении моих тестов селена

Exception in thread "main" 
org.openqa.selenium.StaleElementReferenceException: stale element 
reference: element is not attached to the page document
  (Session info: chrome=63.0.3239.84)
  (Driver info: chromedriver=2.34.522932 ( 
4140ab217e1ca1bec0c4b4d1b148f3361eb3a03e),platform=Mac OS X 10.12.6 
x86_64) (WARNING: The server did not provide any stacktrace 
information)
Command duration or timeout: 0 milliseconds
For documentation on this error, please visit: 
 http://seleniumhq.org/exceptions/stale_element_reference.html
01T19:05:14.666Z'.

Вот код

        List<WebElement> category = 
driver.findElements(By.className("a2s-skill-block"));


for(int i = 0;i<category.size();i++) {

        category.get(i).click();
        Thread.sleep(7000);


        driver.navigate().back();
    //  WebElement skills1 = driver.findElement(By.id("iApps"));
        //skills1.click();
        Thread.sleep(15000);


    }

Я просмотрел похожие посты по этому вопросу и попробовал множество решений, упомянутых другими членами, но почему-то ожидание и ожидаемые решения, похоже, не работают. Любое другое направление мысли действительно ценится.

Вот варианты, которые я пробовал

  1. Увеличено время ожидания с помощью метода Thread.sleep()
  2. Введено ожидание и ожидаемые условия

    WebDriverWait wait = new WebDriverWait(драйвер, 150);

    wait.until (ExpectedConditions.senceOfAllElementsLocatedBy(By.className("text-heading")));

2 ответа

Вы должны потратить некоторое время на чтение и понимание того, что StaleElementReferenceException является. Важно понять, что вызывает это и что делать, чтобы избежать этого.

В этом случае вы очищаете страницу и загружаете category с элементами со страницы 1. Затем вы нажимаете на ссылку, которая переводит вас на страницу 2. В этот момент все ссылки в category устарели, но исключение еще не выдано, потому что вы еще не обращались ни к одной из переменных. Затем вы используете .back() вернуться на страницу 1 и попытаться что-то сделать с category и получите исключение.

Чтобы избежать этого, вам нужно изменить структуру элементов в category на странице 1 после использования .back() с другой страницы. Одним из способов является то, что я написал ниже. Страница очищается внизу каждой петли.

List<WebElement> category = driver.findElements(By.className("a2s-skill-block"));
for (int i = 0; i < category.size(); i++)
{
    category.get(i).click();
    // sleeps are a bad practice, use WebDriverWait instead
    driver.navigate().back();
    driver.findElement(By.id("iApps")).click();
    // sleeps are a bad practice, use WebDriverWait instead
    category = driver.findElements(By.className("a2s-skill-block"));
}

Вы найдете все категории на странице, прежде чем для цикла. Когда вы щелкаете что-то в цикле, чтобы перейти на другую страницу, на самом деле "Ссылка на устаревший элемент" была запущена, без вашего возвращения, наконец, на последнюю страницу.

Нижеуказанные условия вызовут "Ссылку на устаревший элемент"

Состояние 1

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

Вы можете думать, что когда вы входите на страницу, Selenium назначит ссылку на страницу внутри Selenium, даже если вы зашли на ту же страницу, но Selenium не может знать, что они совпадают, поэтому она назначит новую ссылку.

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

Состояние 2

Оставайтесь на странице (не покидайте ее), но ваш скрипт вызвал HTML DOM-узел найденных элементов, изменив / повторно подключив / удалив. например, какой-либо атрибут узла DOM был изменен, или узел DOM удален и добавлен снова, и все атрибуты не изменились.

Таким образом, любое изменение / перемещение на DOM-узле найденных элементов вызовет "Stale Element Refrence". Вы можете думать, что Условие 1 - это просто еще один способ изменить / переместить DOM Node.

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

Ниже кода предположим, что каждая категория имеет уникальный текст:

List<WebElement> category = 
    driver.findElements(By.className("a2s-skill-block"));

List<String> categoryTexts = new ArrayList<String>();

for(WebElement it: category) {
    categoryTexts.add(it.getText());
}

for(int i = 0;i<category.size();i++) {

    driver.findElement(By.xpath("//*[text()='"+categoryTexts.get(i)+"']")).click();
    Thread.sleep(7000);

    driver.navigate().back();
    Thread.sleep(15000);
Другие вопросы по тегам