Объектная модель страницы (POM) и фабрика страниц в Selenium

Что такое объектная модель страницы?

Объектная модель страницы (POM) — это шаблон проектирования, широко используемый в автоматизации тестирования, который создает репозиторий объектов для элементов веб-интерфейса. Преимущество модели в том, что она уменьшает дублирование кода и улучшает обслуживание тестов.

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

Объектная модель страницы

Почему объектная модель страницы?

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

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

Объектная модель страницы

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

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

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

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

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

Объектная модель страницы

Преимущества ПОМ

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

Как реализовать ПОМ?

Простой ПОМ:

Это базовая структура объектной модели страницы, в которой все веб-элементы AUT и метод, который работает с этими веб-элементами, хранится внутри файла класса. Такая задача, как проверка, должна быть отдельной как часть методов тестирования.

Внедрить ПОМ

Полный пример

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

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

Внедрить ПОМ

Шаг 2) На главной странице проверьте текст «Guru99 Bank».

Внедрить ПОМ

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

Внедрить ПОМ

Шаг 4) Убедитесь, что на домашней странице содержится текст «Идентификатор менеджера: демо».

Внедрить ПОМ

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

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

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

Guru99 Страница входа POM

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();        
    }

}

Домашняя страница Guru99 POM в Selenium

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 Простой POM в тестовом примере Selenium

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?

Фабрика страниц в Selenium — это встроенная концепция платформы объектной модели страницы для Selenium WebDriver, но она очень оптимизирована. Он используется для инициализации объектов Page или для создания экземпляра самого объекта Page. Он также используется для инициализации элементов класса Page без использования «FindElement/s».

Здесь мы также следуем концепции разделения репозитория объектов страницы и методов тестирования. Дополнительно с помощью класса PageFactory в Selenium мы используем аннотации @FindBy чтобы найти ВебЭлемент. Мы используем метод initElements для инициализации веб-элементов.

Фабрика страниц в Selenium

@FindBy могу принять имя тега, частичный текст ссылки, имя, текст ссылки, идентификатор, CSS, имя класса, 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 с фабрикой страниц

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 TestCase с концепцией 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"));

    }

}

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

Фабрика страниц в Selenium

AjaxElementLocatorFactory

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

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

Фабрика локаторов AjaxElement

Выводы

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

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