Перейти к содержимому

Фотография

Selenide : наследование PageObject'ов и NullPointer


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 6

#1 elvis

elvis

    Постоянный участник

  • Members
  • PipPipPip
  • 189 сообщений
  • Город:Tallinn


Отправлено 12 сентября 2015 - 12:48

До сих пор не пользовался Селенидом, но возникла необходимость его применения и на первых порах столкнулся с проблемой. Дело в том, что я привык явно задавать драйвер и передавать его инстанцию всем PageObject'ам, которые инициализирую, а там дальше уже обо всём заботится PageFactory. Тут же получается нет такой необходимости? Я не задаю явно вебдрайвер и тем не менее по умолчанию запускается Firefox. Это конечно неплохо, но как инициализировать PageObject'ты? Нашёл в документации вот это:

GoogleSearchPage searchPage = open("/login", GoogleSearchPage.class);

А как поступать тогда со страницами, которые наследуют (extends) этот класс? У меня никак не получается это сделать. Я к тому же использую аннотации @FindBy, но получаю в итоге NullPointer при обращении к элементам. Может кто-нибудь приведёт пример?

Приведу пока свой пример:
Это основной класс

public class ParentClass{ 

    @FindBy(xpath="//button[@class='test']")
    private SelenideElement myButton;

    .....
    ....
    ....

    public ChildClass getSomeTab(){
        myButton.click();
        return new ChildClass();
    }
}

Это класс который наследует от основного

public class ChildClass extends ParentClass{
    @FindBy(id="someId")
    private SelenideElement header;
    .....
    .....
    .....
    public String getHeaderText(){
        return header.getText();
    }
}

Теперь сам тест, который благополучно падает с NullPointer'ом при попытке получить текст из элемента на дочернем объекте.

@Test
public void dummyTest(){
    ParentClass myPage = Selenide.open(mySiteURL, ParentClass.class);
    ChildClass someTab = myPage.getSomeTab();
    assertEquals(someTab.getHeaderText(), "Expected Text");
}

Очевидно, селенид не передаёт объект драйвера дочернему классу, но как это сделать правильно, сохранив структуру и логику объектов? С PageFactory мне достаточно было передавать объект драйвера который я создал ранее в конструктор класса и делать initPageElements();


  • 0

#2 elvis

elvis

    Постоянный участник

  • Members
  • PipPipPip
  • 189 сообщений
  • Город:Tallinn


Отправлено 12 сентября 2015 - 13:04

Хотелось бы дополнить, что меня интересует именно вариант с аннотациями @FindBy. Если использовать в методах дочернего класса $(By) то всё работает, но мне этот вариант не особо нравится.


  • 0

#3 Saga

Saga

    Новый участник

  • Members
  • Pip
  • 37 сообщений
  • ФИО:Maryna Kolesnik
  • Город:Киев


Отправлено 12 сентября 2015 - 14:17

public class ParentClass{ 


@FindBy(xpath="//button[@class='test']")
private SelenideElement myButton;


.....
....
....


public ChildClass getSomeTab(){
    myButton.click();
    return page(ChildClass.class);
}
}

http://selenide.org/...ge-objects.html

http://ru.selenide.o...ge-objects.html


  • 1

#4 elvis

elvis

    Постоянный участник

  • Members
  • PipPipPip
  • 189 сообщений
  • Город:Tallinn


Отправлено 12 сентября 2015 - 14:53

спасибо!


  • 0

#5 asolntsev

asolntsev

    Новый участник

  • Members
  • Pip
  • 64 сообщений
  • ФИО:Андрей Солнцев
  • Город:Таллинн

Отправлено 13 сентября 2015 - 05:22

Точно, для инициализации страницы нужно использовать метод page(ChildClass.class);

 

P.S. А почему вариант $(By) не нравится?


  • 0

#6 elvis

elvis

    Постоянный участник

  • Members
  • PipPipPip
  • 189 сообщений
  • Город:Tallinn


Отправлено 13 сентября 2015 - 12:42

Точно, для инициализации страницы нужно использовать метод page(ChildClass.class);

 

P.S. А почему вариант $(By) не нравится?

 

Предпочитаю видеть все локаторы вверху класса, а в теле метода исключительно переменные. В принципе можно заменить все переменные элементов на переменные By, но тогда визуально не так бросается в глаза (всё таки @FindBy выделяется в IDE другим цветом) и они могут затеряться среди полей другого типа или констант.

 

Кстати не подскажете, почему в конструкторе класса не получается поставить такое ожидание?
 

myElement.waitUntil(Condition.visible, 3);

получаю

java.lang.RuntimeException: Failed to create new instance of class ChildClass
at com.codeborne.selenide.Selenide.page(Selenide.java:429)

однако прокатывает , если написать вот так

$(By.xpath(elementXpath)).waitUntil(Condition.visible, 3);

  • 0

#7 asolntsev

asolntsev

    Новый участник

  • Members
  • Pip
  • 64 сообщений
  • ФИО:Андрей Солнцев
  • Город:Таллинн

Отправлено 13 сентября 2015 - 21:49

Ну, потому что в конструкторе объект ещё не создан, его поля ещё не инициализированы. Поэтому myElement равен null.
  • 0


Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных