Баг в Selenium WebDriver (программа проверки битых ссылок)
От: Psihadelic  
Дата: 20.10.13 11:41
Оценка:
Здравствуйте товарищи!

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


int look(IWebElement el)
        {
            el.Click(); //переходим по переданному элементу (у нас это ссылка)
            if (find(driver.Url)) //Проверяем не посещали ли мы еще эту страницу (реализация проверки не важна, она работает)
            {
                return 0;
            }
            else //Если не посылали
            {
                pagesWithError.Add(driver.Url); //Добавляем в список адрес страницы (driver это IWebDriver driver; созданный как член касса)
                try
                {
                    IList<IWebElement> elements = driver.FindElements(By.TagName("a")); //Ищем ссылки на странице
                    if (elements.Count != 0) //если ссылки есть
                    {
                        for (int i = 0; i < elements.Count; ++i) 
                        {
                            look(elements[i]); //заходим по-очереди на ссылки
                        }
                    }
                }
                catch (UnexpectedTagNameException)
                {
                    return 0;
                }

                return 0;
            }
        }


Ну а теперь суть проблемы: если на странице более одной ссылки (допустим две), то когда мы проверяем первую ссылку и возвращаемся к проверке второй, элементы IList<IWebElement> elements почему-то обнуляются что приводит к ошибке после вызова метода el.Click(); (говорит что элемент не существует).
Т.е. проблема в том, что когда мы рекурсивно возвращаемся в цикл для второй итерации, элементы в списке уже не те. Это глюк силениума или я что-то не так делаю?
Re: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: sunshine Россия https://angel.ru/?src=rsdn
Дата: 21.10.13 12:03
Оценка: 3 (1) +1 :)
Такое ощущение, что у вас объект driver общий для всех страниц. Его нужно для каждой страницы (и, следовательно, для каждой ссылки) отдельно создавать в вашем сценарии.
Если этого не делать, то все объекты элементов страниц, полученные для некоторого URL, перестанут быть актуальными после того, как объект driver, при помощи которого они получены, получит новый URL.
Принимаю платежи в любой валюте
Re[2]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: Psihadelic  
Дата: 21.10.13 16:03
Оценка:
Здравствуйте, sunshine, Вы писали:

S>Такое ощущение, что у вас объект driver общий для всех страниц. Его нужно для каждой страницы (и, следовательно, для каждой ссылки) отдельно создавать в вашем сценарии.

S>Если этого не делать, то все объекты элементов страниц, полученные для некоторого URL, перестанут быть актуальными после того, как объект driver, при помощи которого они получены, получит новый URL.

И то правда, я его создал как член класса. Спасибо большое за объяснение, попытаюсь исправить ошибку. Но скажите, а где это в документации написано или как логично обосновывается? И то я чет не очень пойму как так происходит.
Re[2]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: Psihadelic  
Дата: 21.10.13 16:09
Оценка:
Здравствуйте, sunshine, Вы писали:

S>Такое ощущение, что у вас объект driver общий для всех страниц. Его нужно для каждой страницы (и, следовательно, для каждой ссылки) отдельно создавать в вашем сценарии.

S>Если этого не делать, то все объекты элементов страниц, полученные для некоторого URL, перестанут быть актуальными после того, как объект driver, при помощи которого они получены, получит новый URL.

Попробовал создавать driver каждый раз. Во-первых, получается что создается куча окон браузера (что уже не желательно), во-вторых, это не решило проблему, к сожалению ошибка та же, при создании нового драйвера, элемент сразу теряет все данные.
Re[3]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: sunshine Россия https://angel.ru/?src=rsdn
Дата: 21.10.13 16:28
Оценка: 3 (1)
Здравствуйте, Psihadelic, Вы писали:

P>Попробовал создавать driver каждый раз. Во-первых, получается что создается куча окон браузера (что уже не желательно), во-вторых, это не решило проблему, к сожалению ошибка та же, при создании нового драйвера, элемент сразу теряет все данные.


То, что при создании нового драйвера элемент теряет данные — это конечно ненормально. Покажите код, в котором вы эти элементы используете, может в нем что-то не так? Я, правда, Селениум из-под Руби использовал, но думаю, везде принцип одинаковый, разве что названия методов и сигнатура чуть различаются...
Во всяком случае, суть в том, что если у вас в объект драйвера загружен некоторый URL (и при этом висит соответствующее окно браузера), то, пока это окно браузера не закрыто, вы можете получить любые свойства для уже полученной коллекции элементов. Если же окно браузера закрылось, или вы при получении свойств элементов подсовываете не тот объект драйвера, или в браузере на данный момент уже загружен другой URL, то загруженная коллекция элементов будет уже невалидной. В Руби при этом вылетает эксепшен типа "элемент несуществует" или что-то в этом духе. Могу предположить, что в вашей обертке для Селениум они обнуляются. Ну или это таки глюк обертки, если у вас все правильно сделано.

То, что куча окон создается, тут ничего не попишешь, ведь так и должно быть, поскольку объект driver == окно(закладка) браузера.
Но, для проверки битых ссылок, Селениум, имхо, это как из пушки по воробьям. Вроде бы достаточно было бы загружать html страницы и проверять регулярным выражением — есть-ли там то, что нужно?
Принимаю платежи в любой валюте
Re[4]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: sunshine Россия https://angel.ru/?src=rsdn
Дата: 21.10.13 16:31
Оценка:
Здравствуйте, sunshine, Вы писали:

S>То, что при создании нового драйвера элемент теряет данные — это конечно ненормально.


Я, пожалуй, неудачно выразился. Не то чтобы элемент теряет данные. Точнее, он становится неспособен получить данные из страницы. Когда вы, например, хотите получить из элемента значение некоторого атрибута, то каждый раз происходит обращение к странице (т.е. там не кешируется ничего). Поэтому может создаться впечатление, что элемент потерял данные.
Принимаю платежи в любой валюте
Re[4]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: Psihadelic  
Дата: 22.10.13 09:05
Оценка:
Здравствуйте, sunshine, Вы писали:

S>То, что куча окон создается, тут ничего не попишешь, ведь так и должно быть, поскольку объект driver == окно(закладка) браузера.

S>Но, для проверки битых ссылок, Селениум, имхо, это как из пушки по воробьям. Вроде бы достаточно было бы загружать html страницы и проверять регулярным выражением — есть-ли там то, что нужно?

Хочется сделать через силениум, для лучшего его освоения. Все верно, во время работы методов класса, драйвер загружет разные страницы. Но ведь если мы до этого все элементы поместили в коллекцию, разве они не должны там остаться? Кроме того, мы ведь используем рекурсию, данные вроде как должны оставаться... Бросаю код для проверки:


class LinkChecker
    {
        IWebDriver driver;
        IList<IWebElement> elements;

        List<String> pagesWithError;

        public LinkChecker()
        {
            driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("file:///C:/Users/Psihadelic/Desktop/site/1.html");
            pagesWithError = new List<String>();
        }

        bool find(string link)
        {
            foreach (String er in pagesWithError)
            {
                if (link == er)
                {
                    return true;
                }
            }

            return false;
        }

        int look(IWebElement el) //Метод который выдает ошибку
        {
            el.Click(); //Ошибка получается тут
            if (find(driver.Url))
            {
                return 0;
            }
            else
            {
                pagesWithError.Add(driver.Url);
                try
                {
                    elements = driver.FindElements(By.TagName("a"));
                    if (elements.Count != 0)
                    {
                        for (int i = 0; i < elements.Count; ++i)
                        {/* допустим есть три страницы, на первой из них две ссылки, на остальных по одной. 
                          * идем по первой ссылке на первой странице, обходим все остальные страницы и возвращаемся ко 
                          * второй - еще не проверенной ссылке. И вот когда эту вторую ссылку из elements мы передаем в look(), данные уже потеряны
                          */
                            look(elements[i]);
                        }
                    }
                }
                catch (UnexpectedTagNameException)
                {
                    return 0;
                }

                return 0;
            }
        }


        public List<String> search() //метод, который вызываем из вне.
        {
            elements = driver.FindElements(By.TagName("a"));
            foreach (IWebElement el in elements)
            {
                look(el);
            }

            return this.pagesWithError;
        }
    }
Re[5]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: sunshine Россия https://angel.ru/?src=rsdn
Дата: 22.10.13 11:14
Оценка:
Здравствуйте, Psihadelic, Вы писали:

В таком виде, вроде бы, должно работать... А как текст ошибки выглядит?
Принимаю платежи в любой валюте
Re[6]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: sunshine Россия https://angel.ru/?src=rsdn
Дата: 22.10.13 11:24
Оценка:
Здравствуйте, sunshine, Вы писали:

S>Здравствуйте, Psihadelic, Вы писали:


S>В таком виде, вроде бы, должно работать... А как текст ошибки выглядит?


Хотя нет. Смотрите, допустим, у вас на странице две ссылки. На первой итерации по ним ошибки не будет. Но при вызове look(IWebElement el) для второй ссылки будет ошибка, потому что драйвер-то уже ушел на другой URL. Поэтому вторая ссылка оказывается принадлежащей к той странице, с которой драйвер уже ушел. И когда вы делаете клик по этой ссылке, вылетает ошибка. А все потому, что нужно для каждого ссылочного элемента сохранять свой индивидуальный драйвер.
Принимаю платежи в любой валюте
Re[7]: Баг в Selenium WebDriver (программа проверки битых ссылок)
От: Psihadelic  
Дата: 22.10.13 14:28
Оценка:
Здравствуйте, sunshine, Вы писали:

S>Хотя нет. Смотрите, допустим, у вас на странице две ссылки. На первой итерации по ним ошибки не будет. Но при вызове look(IWebElement el) для второй ссылки будет ошибка, потому что драйвер-то уже ушел на другой URL. Поэтому вторая ссылка оказывается принадлежащей к той странице, с которой драйвер уже ушел. И когда вы делаете клик по этой ссылке, вылетает ошибка. А все потому, что нужно для каждого ссылочного элемента сохранять свой индивидуальный драйвер.


Могли бы Вы написать примерчик? Потому как у меня не получилось это сделать.

Текст ошибки:
Element not found in the cache — perhaps the page has changed since it was looked up
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.