Объектная модель страницы (Page Object Model – POM) – это шаблон проектирования, широко используемый в автоматизации тестирования. В этой статье мы рассмотрим использование POM в Selenium.
Содержание
- В чем суть применения POM в Selenium?
- Преимущества POM
- Как реализовать POM?
- Что такое Page Factory в Selenium?
- Тест-кейс Guru99 с использованием Page Factory
- AjaxElementLocatorFactory
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ
В чем суть применения POM в Selenium?
Паттерн POM предполагает создание репозитория объектов для элементов веб-интерфейса. Преимуществом здесь является уменьшение дублирования кода и улучшение сопровождения тестов.
Согласно этой модели, для каждой веб-страницы в приложении должен существовать соответствующий класс Page
. Он будет идентифицировать элементы данной веб-страницы, а также содержать методы Page
, выполняющие операции с этими элементами. Имя этих методов должно соответствовать выполняемой ими задаче. Т.е., если загрузчик ожидает появления платежного шлюза, то имя метода POM может быть waitForPaymentScreenDisplay()
.
Переходим к использованию паттерна POM в Selenium.
Запуск автоматизации пользовательского интерфейса в Selenium WebDriver – не самая сложная задача. Нужно просто найти элементы и выполнить над ними операции.
Рассмотрим этот простой сценарий для входа на сайт:
Как можно заметить, все, что мы делаем, – это поиск элементов и заполнение их значениями.
Это небольшой скрипт. Его сопровождение выглядит достаточно просто. Но со временем набор тестов будет расти. По мере того, как вы добавляете в код все больше и больше строк, он становится сложнее.
Основная проблема при обслуживании скриптов заключается в том, что если 10 различных скриптов используют один и тот же элемент страницы, то при любом изменении этого элемента необходимо изменить все 10 скриптов. Это отнимает много времени и чревато ошибками.
Более эффективным подходом к обслуживанию скриптов является создание отдельного файла класса, который будет находить веб-элементы, заполнять их или проверять. Этот класс может быть повторно использован во всех скриптах, использующих данный элемент. В будущем, если в веб-элементе произойдет изменение, нам нужно будет исправить всего в один файл класса, а не 10 различных скриптов.
Такой подход в Selenium называется объектной моделью страницы (POM). Он позволяет сделать код более читаемым, сопровождаемым и многократно используемым.
Преимущества POM
- Паттерн POM предполагает, что операции и потоки в пользовательском интерфейсе должны быть отделены от верификации. Эта концепция делает код чище и проще для понимания.
- Второе преимущество заключается в том, что репозиторий объектов не зависит от тестовых случаев, поэтому мы можем использовать один и тот же репозиторий объектов для разных целей с разными инструментами. Например, мы можем интегрировать объектную модель страницы в Selenium с TestNG/JUnit для функционального тестирования и в то же время с JBehave/Cucumber для приемочного тестирования.
- Благодаря многоразовым методам страниц в классах POM код становится более оптимизированым, а его размер уменьшается.
- Методы получают более реалистичные имена, которые можно легко сопоставить с операцией, происходящей в пользовательском интерфейсе. Например, если после нажатия на кнопку мы попадаем на главную страницу, то имя метода будет выглядеть как
gotoHomePage()
.
Как реализовать POM?
Это базовая структура POM, в которой все веб-элементы AUT (тестируемое приложение – Application Under Testing) и метод, работающий с этими веб-элементами, хранятся внутри файла класса. Такая задача, как проверка, должна быть выделена в отдельную часть методов Test
.
Пример реализации POM
Шаг 1. Перейдите на демонстрационный сайт Guru99.
Шаг 2. На главной странице проверьте наличие текста “Guru99 Bank”.
Шаг 3. Войдите в приложение.
Шаг 4. Убедитесь, что на главной странице присутствует текст “Manger Id: demo”.
Здесь мы имеем дело с 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
может принимать в качестве атрибутов 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.
Выводы
- Объектная модель страницы в Selenium WebDriver представляет собой паттерн проектирования Object Repository.
- Объектная модель страниц Selenium позволяет сделать наш код тестирования сопровождаемым и многократно используемым.
- Page Factory – это оптимизированный способ создания хранилища объектов в концепции Page Object Model.
- AjaxElementLocatorFactory – это концепция отложенной загрузки в Page Factory, позволяющая идентифицировать веб-элементы только тогда, когда они используются в какой-либо операции.
Перевод статьи «Page Object Model (POM) & Page Factory in Selenium».
Пингбэк: 25 вопросов на собеседовании по Playwright
Пингбэк: Большой учебник по Selenium
Пингбэк: Вопросы по Appium на собеседовании