Как стать автором
Обновить

«Элементарный» Вор или плата за использование Selenide

Уровень сложностиПростой
 «Селенид ворует элемент» - неизвестный художник, наше время.
 «Селенид ворует элемент» - неизвестный художник, наше время.

Однажды, в одном из супермаркетов, при оплате пластиковой картой, у меня произошло двойное списание, и, позвонив в один, всем известный банк, я узнал, что у них произошел какой-то сбой, и проблема массовая, но на вопрос когда же все-таки мне вернут мои деньги, я услышал:

Деньги вы держите в нашем банке, так? - Так. А значит они не ваши, а наши. Вот когда захотим, тогда и вернем! *короткие гудки*

Не сказать, что я был удивлен подобным ответом, да и деньги конечно по итогу вернули, но случай был необычный.

Так вот в данной мини-статье я, ничего не подозревая, как и в случае двойного списания средств, описанного абзацем выше, сидел себе писал код тестов на Java, используя Selenide, и вдруг, заметил самую настоящую «магию»!

Немного мнения о Selenid'е

Многие знают, что это широко известный в узких (QA) кругах, базирующийся на более известном, в более широких кругах, инструмент для автоматизации тестирования UI, в частности, WEB-тестирования. Не буду углубляться в холиварное «Selenium vs Selenide», но стоит отметить, что Selenide сделан на базе Selenium, так же в его библиотеках доступны «селенеумовские» методы и классы. Но любовь пользователей он имхо заслужил за более краткий синтаксис а-ля: $$(elementsXPath), $$(elementsSelector) и т п; за отсутствие необходимости настройки и конфигурирования (в частности указания пути к исполняемому файлу WebDriver.exe) - хотя кое-какое конфигурирование все равно присутствует в селениде; возможность обходиться безsleeps и waits на каждом углу;  удобная работа с приложениями с Ajax-вызовами; и наверное есть еще какая-то вкусовщина в пользу селенида, но думаю, она незначительна. Мне на самом деле не принципиален выбор между двумя этими инструментами, но вот «магия» описанная ниже, немного пошатнула мое доверие к селениду...

Итак, от слов к делу. Нам понадобится:

  • IDE (например Intelij Idea, версия думаю не принципиальна уж сами понимаете)

  • Gradle (или любой другой сборщик для Java)

  • Selenide ('com.codeborne:selenide:6.12.3' //последняя на момент написания статьи)

  • Java 8 (думаю тоже не принципиально, но тестировал на восьмой)

Ниже приведен самый банальный код:

public class Main {
    public static void main(String[] args) {
        //создаем список элементов «сграбленных» с таблицы сайта:
        List<SelenideElement> items = $$x(tableItemsPath);//допустим их там 50 шт.
        //создаем лист ал-ля взять первые, пусть например 3, элемента:
        List<SelenideElement> actualList = items.subList(0, 3);
        //создаем «буферный» лист для эксперимета:
        List<SelenideElement> expectedList = new ArrayList<>();
        /*циклом итерируемся по actualList, добавляя в наш буфер actualList
        элемент  на каждой итерации: */
        for (SelenideElement elem : actualList) {
            expectedList.add(elem);
        }

        //и тут, казалось бы проитерировались...
        //записали все элементы в новый список...
        //и оба списка должны содержать одинаковое кол-во элементов...
        //Но! Как бы ни так!

        System.out.println("expected list size: " + expectedList.size());
        System.out.println("actual list size: " + actualList.size());
        System.out.println("expected list: " + expectedList);
        System.out.println("actual list: " + actualList);
    }
}

Ну и собственно вывод консоли:

Можем проверить на наличие null в списке:

       //так:

        items.subList(0, 3).forEach(e -> {
            assert e != null;
        });

       //или так:

        assert !items.subList(0, 3).contains(null);

А вот и разгадка:

        AtomicInteger x = new AtomicInteger();
        items.subList(0, 3).forEach(e -> {
            x.addAndGet(1);
        });

        System.out.println("it's about magic: " + x); //it's about magic: 2

Виновник этого «волшебства» кроется в методе .subList(); поскольку «селенидовский» лист, возвращаемый функцией $$x, хоть и имплементирует java.util.List, видимо имеет кривые методы под капотом, благодаря которым, при итерировании по коллекции совершаем на 1 итерацию меньше.

Вообще говоря это мой первый опыт с Selenide, до этого я пользовался Selenium. Код выше, естественно для примера. И с описанной проблемой, я столкнулся, написав уже не один с десяток файлов кода в проекте. А сами знаете кто, сами знаете в чём кроется. Но вот, что бы этого кого-то найти, пришлось постараться. Признаюсь честно. Горело пока искал.

P.S. За сим прощаюсь, до скорого!

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.