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

Фотография

Что дает использование PageFactory?


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

#1 vitaliy4us

vitaliy4us

    Активный участник

  • Members
  • PipPip
  • 81 сообщений

Отправлено 11 марта 2016 - 16:30

Не понимаю необходимости использования класса PageFactory. По-моему, без него все выглядит гораздо проще и логичнее. Ну вот, например, создадим два класса: PageObjectWithPageFactory и PageObjectWithoutPageFactory и воспользуемся ними для работы с объектом PageObject.

 

В первом случае имеем:

package selenium;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;

public class PageObjectWithPageFactory {
    WebDriver driver;
    @FindBy(how=How.ID, id="lst-ib")
    WebElement fieldSearch;
    @FindBy(how=How.NAME, name="btnK")
    WebElement btnSearch;
    public PageObjectWithPageFactory(WebDriver driver){
        this.driver = driver;
        driver.get("https://www.google.com.ua");
    }
    public void find(){
        fieldSearch.sendKeys("Искать что-нибудь");
        btnSearch.click();
    }
    
}

и соответственно его реализация:

public class Selenium {
    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        PageObjectWithPageFactory page = PageFactory.initElements(driver, PageObjectWithPageFactory.class);
        page.find();
    }
}

Во втором случае:

package selenium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class PageObjectWithoutPageFactory {
    WebDriver driver;
    WebElement fieldSearch;
    WebElement btnSearch;
    
    public PageObjectWithoutPageFactory(WebDriver driver){
        this.driver = driver;
        driver.get("https://www.google.com.ua");
        fieldSearch = driver.findElement(By.id("lst-ib"));
        btnSearch = driver.findElement(By.name("btnK"));
    }
    public void find(){
        fieldSearch.sendKeys("Искать что-нибудь");
        btnSearch.click();
    }
    
}

и его реализация:

public class Selenium {
    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        PageObjectWithoutPageFactory page = new PageObjectWithoutPageFactory(driver);
        page.find();
    }
}

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


  • 0

#2 barancev

barancev

    Администратор

  • Admin
  • PipPipPipPipPipPip
  • 6 872 сообщений
  • ФИО:Алексей Баранцев
  • Город:Россия, Москва


Отправлено 11 марта 2016 - 19:21

Чтобы увидеть разницу, нужно переписать пример, скажем, вот так:

public class Selenium {
    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        PageObjectWithoutPageFactory page = new PageObjectWithoutPageFactory(driver);
        driver.get("https://www.google.com.ua");
        page.find();
    }
}

  • 1
Алексей Баранцев
Тренинги для тестировщиков (тестирование производительности, защищенности, тест-дизайн, автоматизация):
Линейка тренингов по Selenium

#3 vitaliy4us

vitaliy4us

    Активный участник

  • Members
  • PipPip
  • 81 сообщений

Отправлено 11 марта 2016 - 19:47

 

Чтобы увидеть разницу, нужно переписать пример, скажем, вот так:

public class Selenium {
    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        PageObjectWithoutPageFactory page = new PageObjectWithoutPageFactory(driver);
        driver.get("https://www.google.com.ua");
        page.find();
    }
}

 

Что то не доходит. Ну вот скажем так, зачем нужен этот класс, если без него все то же самое можно сделать с тем же успехом? Создается впечатление, что это просто усложнение простого пути без видимых на то причин.


  • 0

#4 barancev

barancev

    Администратор

  • Admin
  • PipPipPipPipPipPip
  • 6 872 сообщений
  • ФИО:Алексей Баранцев
  • Город:Россия, Москва


Отправлено 11 марта 2016 - 20:14

А Вы попробовали выполнить этот пример? Получили StaleElementReferenceException? Причину выявили? Придумали, как доработать код, чтобы избежать появления этого исключения? Сравнили полученный результат повторно с тем примером, где используется PageFactory?

 

(P.S. Я не агитирую за использование PageFactory и сам его практически никогда не использую, просто пытаюсь показать, в чём разница между этими двумя примерами)


  • 0
Алексей Баранцев
Тренинги для тестировщиков (тестирование производительности, защищенности, тест-дизайн, автоматизация):
Линейка тренингов по Selenium

#5 DennisM

DennisM

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

  • Members
  • Pip
  • 55 сообщений
  • ФИО:Dennis M
  • Город:Ralegh NC, USA

Отправлено 11 марта 2016 - 20:33

По опыту оно приносит больше вреда чем пользы. На соседнем проекте использовали это. Потом посмотрели на наш автомейшн и забили на PageFactory.
PageObject надо использовать, PageFactory нет..

  • 0

#6 vitaliy4us

vitaliy4us

    Активный участник

  • Members
  • PipPip
  • 81 сообщений

Отправлено 12 марта 2016 - 11:58

А Вы попробовали выполнить этот пример? Получили StaleElementReferenceException? Причину выявили? Придумали, как доработать код, чтобы избежать появления этого исключения? Сравнили полученный результат повторно с тем примером, где используется PageFactory?

 

(P.S. Я не агитирую за использование PageFactory и сам его практически никогда не использую, просто пытаюсь показать, в чём разница между этими двумя примерами)

Да, пробовал, получал Exception, но в обоих случаях - и с PageFactory и без него. Это происходит из-за "пропажи" гугловской кнопки после ввода строки поиска. Если не выполнять клик по этой кнопке, то все работает одинаково, ровно как и на других примерах, не связанных с гуглом. Вот поэтому то я и не могу понять. Я же не возражаю и понимаю, что "если звезды зажигают, то это кому-нибудь нужно". А зачем их зажигают разобраться не могу.


  • 0

#7 vitaliy4us

vitaliy4us

    Активный участник

  • Members
  • PipPip
  • 81 сообщений

Отправлено 12 марта 2016 - 12:00

 

По опыту оно приносит больше вреда чем пользы. На соседнем проекте использовали это. Потом посмотрели на наш автомейшн и забили на PageFactory.
PageObject надо использовать, PageFactory нет..

 

Ну спасибо, хоть немного успокоили, а то я думал, что уж совсем туп.


  • 0

#8 elvis

elvis

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

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


Отправлено 12 марта 2016 - 12:37

Можете написать PageFactory.initElements в конструкторе PageObject и тогда не надо будет его писать каждый раз. Во всяком случае будет доступна ленивая инициализация елементов PageObject.


  • 0

#9 fiatlux

fiatlux

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

  • Members
  • Pip
  • 47 сообщений

Отправлено 12 марта 2016 - 19:30

А что если в теле класса PageObject'а хранить final поля типа By сразу инициализировав их?

Дальше эти By поля передавать скажем селенидовским $ и $$ в телах методов PageObject'а.

public class SomePage {
    private static final By BUTTON_SEARCH = By.id("someId123");
    private static final By FIELD_SEARCH = By.id("someId456");


    public void setSearchText(String text) {
        $(FIELD_SEARCH).setText(text);
    }


    public void clickSearch() {
        $(BUTTON_SEARCH).click();
    }
}
 
Плюсы и минусы относительно @FindBy скажем? Что думаете?

  • 0

#10 barancev

barancev

    Администратор

  • Admin
  • PipPipPipPipPipPip
  • 6 872 сообщений
  • ФИО:Алексей Баранцев
  • Город:Россия, Москва


Отправлено 12 марта 2016 - 19:33

Да, пробовал, получал Exception, но в обоих случаях - и с PageFactory и без него. Это происходит из-за "пропажи" гугловской кнопки после ввода строки поиска. Если не выполнять клик по этой кнопке, то все работает одинаково, ровно как и на других примерах, не связанных с гуглом. Вот поэтому то я и не могу понять. Я же не возражаю и понимаю, что "если звезды зажигают, то это кому-нибудь нужно". А зачем их зажигают разобраться не могу.

 

Вы не обратили внимание на то, что там были *разные* исключения.


  • 0
Алексей Баранцев
Тренинги для тестировщиков (тестирование производительности, защищенности, тест-дизайн, автоматизация):
Линейка тренингов по Selenium

#11 TatyanaV

TatyanaV

    Опытный участник

  • Members
  • PipPipPipPip
  • 388 сообщений
  • ФИО:Воробьева Татьяна


Отправлено 17 марта 2016 - 11:57

Я активно использую PageFactory.

Разница в том, что в вашем примере - одна абстрактная страница. У меня в проекте страниц уже много.

За счет PageFactory - я вообще не занимаюсь их инициализацией, я просто обращаюсь к PageFactory при необходимости. Т.к. страниц действительно много - они уже разделены у меня на пару блоков. Для одних тестов инициализируется один набор таблиц, для других - другой и т.д.. И все - через один класс, который при необходимости уже сам может вызвать другой класс.

При этом, через все тот же PageFactory у меня есть удобная возможность управлять всем, что связано со страницами (к примеру, таймаутами и т.п.) внутри ОДНОГО класса (PageFactory), а не лазить по файлам со страницами.

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


  • 0

#12 asolntsev

asolntsev

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

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

Отправлено 28 марта 2016 - 20:52

Привет!

Я тоже считаю, что PageFactory не нужна. Более того, я думаю, что объявление элементов как полей класса пэдж-обжекта - неправильно. Это компроментирует одно из ключевых понятий ООП (ведь пэдж-обжект - это объект, верно?) - инкапсуляцию.

 

Смотрите, как можно сделать Page Object ещё гораздо проще. Без всяких фактори.

 

import static com.codeborne.selenide.*;

public class ReallySimplePageObject {
    public void find(String word){
        $("#lst-ib").sendKeys("Искать что-нибудь");
        $(By.name("btnK")).click();
    }   
}

@Test
public void canSearchWithGoogle() {
  ReallySimplePageObject searchPage = open("https://www.google.com.ua", ReallySimplePageObject.class);
  searchPage.find("Искать что-нибудь");
}

  • 0

#13 elvis

elvis

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

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


Отправлено 29 марта 2016 - 05:51

 

Привет!

Я тоже считаю, что PageFactory не нужна. Более того, я думаю, что объявление элементов как полей класса пэдж-обжекта - неправильно. Это компроментирует одно из ключевых понятий ООП (ведь пэдж-обжект - это объект, верно?) - инкапсуляцию.

 

Смотрите, как можно сделать Page Object ещё гораздо проще. Без всяких фактори.

 

import static com.codeborne.selenide.*;

public class ReallySimplePageObject {
    public void find(String word){
        $("#lst-ib").sendKeys("Искать что-нибудь");
        $(By.name("btnK")).click();
    }   
}

@Test
public void canSearchWithGoogle() {
  ReallySimplePageObject searchPage = open("https://www.google.com.ua", ReallySimplePageObject.class);
  searchPage.find("Искать что-нибудь");
}

 

Ага, и копи-пейстить эти локаторы, если они используются в ReallySimplePageObject.class неоднократно? Ведь всякие случаи бывают. Изменится локатор, искать его тоже в методе будете? Безымянный и с трёхэтажным xpath. Тут я не совсем согласен. Лучше объявить эти локаторы By в начале класса. Бывают конечно и исключения.. но на то они и исключения.


  • 0

#14 mike1999

mike1999

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

  • Members
  • Pip
  • 6 сообщений
  • ФИО:Нотлермов Михаил Юрьевич

Отправлено 12 января 2017 - 13:06

А Вы попробовали выполнить этот пример? Получили StaleElementReferenceException? Причину выявили? Придумали, как доработать код, чтобы избежать появления этого исключения? Сравнили полученный результат повторно с тем примером, где используется PageFactory?

 

(P.S. Я не агитирую за использование PageFactory и сам его практически никогда не использую, просто пытаюсь показать, в чём разница между этими двумя примерами)

 

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

 

По сути всем новичками - в указанном примере PageObjectWithoutPageFactory -

 

При выполнении указанного примера разница не будет заметна - и там и там (при поправке на кнопку поиска) все будет работать без всяких исключений. Разница будет заметна только в том случае, если с момента создания объекта страницы элементы будут пересоздаваться - в случае без фактори изначально определенный вебэлемент (fieldSearch = driver.findElement(By.id("lst-ib"));) с момента создания до непосредственного вызова вполне может пропасть из дом (например будет перерисован) и вылезет исключение. Во втором случае поиск элемента на странице происходит при каждом обращении к элементу через объект страницы, т.е. если даже элемент был перерисован, он все-равно отыщется.


  • 1


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

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