POM и Page Factory в Selenium

Объектная модель страницы (Page Object Model – POM) – это шаблон проектирования, широко используемый в автоматизации тестирования. В этой статье мы рассмотрим использование POM в Selenium.

Содержание

Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ

В чем суть применения POM в Selenium?

Паттерн POM предполагает создание репозитория объектов для элементов веб-интерфейса. Преимуществом здесь является уменьшение дублирования кода и улучшение сопровождения тестов.

Согласно этой модели, для каждой веб-страницы в приложении должен существовать соответствующий класс Page. Он будет идентифицировать элементы данной веб-страницы, а также содержать методы Page, выполняющие операции с этими элементами. Имя этих методов должно соответствовать выполняемой ими задаче. Т.е., если загрузчик ожидает появления платежного шлюза, то имя метода POM может быть waitForPaymentScreenDisplay().

финальный вид POM

Переходим к использованию паттерна POM в Selenium.

Запуск автоматизации пользовательского интерфейса в Selenium WebDriver – не самая сложная задача. Нужно просто найти элементы и выполнить над ними операции.

Рассмотрим этот простой сценарий для входа на сайт:

скрипт для входа на веб-сайт, в котором осуществляется поиск элементов и заполнение их значениями

Как можно заметить, все, что мы делаем, – это поиск элементов и заполнение их значениями.

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

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

Более эффективным подходом к обслуживанию скриптов является создание отдельного файла класса, который будет находить веб-элементы, заполнять их или проверять. Этот класс может быть повторно использован во всех скриптах, использующих данный элемент. В будущем, если в веб-элементе произойдет изменение, нам нужно будет исправить всего в один файл класса, а не 10 различных скриптов.

Такой подход в Selenium называется объектной моделью страницы (POM). Он позволяет сделать код более читаемым, сопровождаемым и многократно используемым.

сравнение структур, которые базируются на POM и нет

Преимущества POM

  1. Паттерн POM предполагает, что операции и потоки в пользовательском интерфейсе должны быть отделены от верификации. Эта концепция делает код чище и проще для понимания.
  2. Второе преимущество заключается в том, что репозиторий объектов не зависит от тестовых случаев, поэтому мы можем использовать один и тот же репозиторий объектов для разных целей с разными инструментами. Например, мы можем интегрировать объектную модель страницы в Selenium с TestNG/JUnit для функционального тестирования и в то же время с JBehave/Cucumber для приемочного тестирования.
  3. Благодаря многоразовым методам страниц в классах POM код становится более оптимизированым, а его размер уменьшается.
  4. Методы получают более реалистичные имена, которые можно легко сопоставить с операцией, происходящей в пользовательском интерфейсе. Например, если после нажатия на кнопку мы попадаем на главную страницу, то имя метода будет выглядеть как gotoHomePage().

Как реализовать POM?

Это базовая структура POM, в которой все веб-элементы AUT (тестируемое приложение – Application Under Testing) и метод, работающий с этими веб-элементами, хранятся внутри файла класса. Такая задача, как проверка, должна быть выделена в отдельную часть методов Test.

Реализация POM

Пример реализации POM

Шаг 1. Перейдите на демонстрационный сайт Guru99.

переход на демонстрационный сайт demo.guru99.com/V4/

Шаг 2. На главной странице проверьте наличие текста “Guru99 Bank”.

проверка наличия текста "Guru99 Bank" на главной странице

Шаг 3. Войдите в приложение.

вход в приложение с использованием логина и пароля

Шаг 4. Убедитесь, что на главной странице присутствует текст “Manger Id: demo”.

проверка присутствия текста "Manger Id: demo" на главной странице

Здесь мы имеем дело с 2 страницами:

  1. Страница входа в систему.
  2. Главная страница (отображается после входа в систему).

Соответственно, мы создаем 2 POM в классах Selenium.

POM страницы входа на демо-сайт Guru99:

package pages;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99Login {

    WebDriver driver;

    By user99GuruName = By.name("uid");

    By password99Guru = By.name("password");

    By titleText =By.className("barone");

    By login = By.name("btnLogin");

    public Guru99Login(WebDriver driver){

        this.driver = driver;

    }

    //Set user name in textbox

    public void setUserName(String strUserName){

        driver.findElement(user99GuruName).sendKeys(strUserName);

    }

    //Set password in password textbox

    public void setPassword(String strPassword){

         driver.findElement(password99Guru).sendKeys(strPassword);

    }

    //Click on login button

    public void clickLogin(){

            driver.findElement(login).click();

    }

    //Get the title of Login Page

    public String getLoginTitle(){

     return    driver.findElement(titleText).getText();

    }

    /**

     * This POM method will be exposed in test case to login in the application

     * @param strUserName

     * @param strPasword

     * @return

     */

    public void loginToGuru99(String strUserName,String strPasword){

        //Fill user name

        this.setUserName(strUserName);

        //Fill password

        this.setPassword(strPasword);

        //Click Login button

        this.clickLogin();        
    }

}

POM главной страницы демо-сайта Guru99:

package pages;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99HomePage {

    WebDriver driver;

    By homePageUserName = By.xpath("//table//tr[@class='heading3']");

    

    public Guru99HomePage(WebDriver driver){

        this.driver = driver;

    }

    //Get the User name from Home Page

        public String getHomePageDashboardUserName(){

         return    driver.findElement(homePageUserName).getText();

        }

}
Guru99 Simple POM in Selenium Test case

package test;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.testng.Assert;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import pages.Guru99HomePage;

import pages.Guru99Login;

public class Test99GuruLogin {

    String driverPath = "C:\\geckodriver.exe";
    
    WebDriver driver;

    Guru99Login objLogin;

    Guru99HomePage objHomePage;

    @BeforeTest

    public void setup(){

	System.setProperty("webdriver.gecko.driver", driverPath);
        
        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        driver.get("http://demo.guru99.com/V4/");

    }

    /**

     * This test case will login in http://demo.guru99.com/V4/

     * Verify login page title as guru99 bank

     * Login to application

     * Verify the home page using Dashboard message

     */

    @Test(priority=0)

    public void test_Home_Page_Appear_Correct(){

        //Create Login Page object

    objLogin = new Guru99Login(driver);

    //Verify login page title

    String loginPageTitle = objLogin.getLoginTitle();

    Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank"));

    //login to application

    objLogin.loginToGuru99("mgr123", "mgr!23");

    // go the next page

    objHomePage = new Guru99HomePage(driver);

    //Verify home page

    Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123"));

    }

Что такое фабрика страниц в Selenium?

Фабрика страниц (Page Factory) в Selenium – это встроенная и очень оптимизированния концепция POM для Selenium WebDriver. Ее используют для инициализации объектов Page или для создания экземпляра самого объекта Page. Она также применяется для инициализации элементов класса Page без использования "FindElement/s".

Здесь мы также следуем концепции разделения хранилища объектов страницы и тестовых методов. Кроме того, с помощью класса PageFactory в Selenium мы используем аннотации @FindBy для поиска веб-элементов. Для инициализации веб-элементов мы используем метод initElements.

использование аннотации @FindBy для поиска веб-элементов и метода initElements для их инициализации

@FindBy может принимать в качестве атрибутов tagName, partialLinkText, name, linkText, id, css, className, xpath.

Рассмотрим тот же пример, что и выше, с использованием Page Factory.

Страница входа на сайт Guru99 с использованием Page Factory:

package PageFactory;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.FindBy;

import org.openqa.selenium.support.PageFactory;

public class Guru99Login {

    /**

     * All WebElements are identified by @FindBy annotation

     */

    WebDriver driver;

    @FindBy(name="uid")

    WebElement user99GuruName;

    @FindBy(name="password")

    WebElement password99Guru;    

    @FindBy(className="barone")

    WebElement titleText;

    @FindBy(name="btnLogin")

    WebElement login;

    public Guru99Login(WebDriver driver){

        this.driver = driver;

        //This initElements method will create all WebElements

        PageFactory.initElements(driver, this);

    }

    //Set user name in textbox

    public void setUserName(String strUserName){

        user99GuruName.sendKeys(strUserName);     
    }

    //Set password in password textbox

    public void setPassword(String strPassword){

    password99Guru.sendKeys(strPassword);

    }

    //Click on login button

    public void clickLogin(){

            login.click();

    }  

    //Get the title of Login Page

    public String getLoginTitle(){

     return    titleText.getText();

    }

    /**

     * This POM method will be exposed in test case to login in the application

     * @param strUserName

     * @param strPasword

     * @return

     */

    public void loginToGuru99(String strUserName,String strPasword){

        //Fill user name

        this.setUserName(strUserName);

        //Fill password

        this.setPassword(strPasword);

        //Click Login button

        this.clickLogin();           

    }

}

Главная страница Guru99 с использованием Page Factory:

package PageFactory;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.FindBy;

import org.openqa.selenium.support.PageFactory;

public class Guru99HomePage {

    WebDriver driver;

    @FindBy(xpath="//table//tr[@class='heading3']")

    WebElement homePageUserName;    

    public Guru99HomePage(WebDriver driver){

        this.driver = driver;

        //This initElements method will create all WebElements

        PageFactory.initElements(driver, this);

    }   

    //Get the User name from Home Page

        public String getHomePageDashboardUserName(){

         return    homePageUserName.getText();

        }

}

Тест-кейс Guru99 с использованием Page Factory

package test;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.testng.Assert;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import PageFactory.Guru99HomePage;

import PageFactory.Guru99Login;

public class Test99GuruLoginWithPageFactory {

    String driverPath = "C:\\geckodriver.exe";
    
    WebDriver driver;

    Guru99Login objLogin;

    Guru99HomePage objHomePage; 

    @BeforeTest

    public void setup(){

        System.setProperty("webdriver.gecko.driver", driverPath);
        
        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        driver.get("http://demo.guru99.com/V4/");

    }

    /**

     * This test go to http://demo.guru99.com/V4/

     * Verify login page title as guru99 bank

     * Login to application

     * Verify the home page using Dashboard message

     */

    @Test(priority=0)

    public void test_Home_Page_Appear_Correct(){

        //Create Login Page object

    objLogin = new Guru99Login(driver);

    //Verify login page title

    String loginPageTitle = objLogin.getLoginTitle();

    Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank"));

    //login to application

    objLogin.loginToGuru99("mgr123", "mgr!23");

    // go the next page

    objHomePage = new Guru99HomePage(driver);

    //Verify home page

    Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123"));

    }

}

Полная структура проекта будет выглядеть так, как показано на схеме:

Полная структура проекта

AjaxElementLocatorFactory

AjaxElementLocatorFactory – это концепция отложенной загрузки PageFactory в Selenium. Ее применяют для поиска веб-элементов только тогда, когда эти элементы используются в какой-либо операции. Она назначает таймаут для веб-элементов объектному классу страницы. Класс AjaxElementLocatorFactory является одним из ключевых преимуществ использования паттерна Page Factory в Selenium.

Здесь при выполнении операции над элементом ожидание его видимости начинается только с момента поиска. Если элемент не будет найден в течение заданного интервала времени, выполнение тестового примера выдаст исключение NoSuchElementException.

концепция отложенной загрузки AjaxElementLocatorFactory, которая назначает таймаут для веб-элементов объектному классу страницы

Выводы

  1. Объектная модель страницы в Selenium WebDriver представляет собой паттерн проектирования Object Repository.
  2. Объектная модель страниц Selenium позволяет сделать наш код тестирования сопровождаемым и многократно используемым.
  3. Page Factory – это оптимизированный способ создания хранилища объектов в концепции Page Object Model.
  4. AjaxElementLocatorFactory – это концепция отложенной загрузки в Page Factory, позволяющая идентифицировать веб-элементы только тогда, когда они используются в какой-либо операции.

Перевод статьи «Page Object Model (POM) & Page Factory in Selenium».

3 комментария к “POM и Page Factory в Selenium”

  1. Пингбэк: 25 вопросов на собеседовании по Playwright

  2. Пингбэк: Большой учебник по Selenium

  3. Пингбэк: Вопросы по Appium на собеседовании

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *