Page Object Model и Page Factory — это инструменты в Selenium, которые широко используются в автоматизации тестирования. В этом руководстве я покажу, как использовать Page Object Model и Page Factory в проектах автоматизации Selenium для удобного управления тест-кейсами. Материал будет полезен для начинающих автоматизаторов.
Что такое Page Object Model в Selenium?
Page Object Model («объектная модель страницы»), также известная как POM, — это шаблон проектирования в Selenium, который создаёт хранилище объектов для управления веб-элементами. Он помогает сократить дублирование кода и упрощает поддержку тест-кейсов.
В Page Object Model каждая веб-страница приложения представляется отдельным классом. Этот класс содержит только веб-элементы, относящиеся к данной странице. Используя эти элементы, тестировщики могут выполнять операции на тестируемом веб-сайте.
Преимущества Page Object Model
Простота сопровождения. POM полезен, когда происходит изменение в элементах интерфейса или в действиях. Например, если выпадающий список был заменён на радиокнопку, POM помогает быстро определить, какие страницы или экраны нужно модифицировать. Поскольку каждый экран представлен отдельным Java-классом, можно быстро найти нужный класс и внести изменения. Это делает тест-кейсы более удобными в сопровождении и снижает вероятность ошибок.
Повторное использование кода. Как уже упоминалось ранее, все экраны являются независимыми, поэтому код тестов, написанный для одной страницы, можно повторно использовать в других тестах. Это избавляет от необходимости повторно писать код, что экономит время и усилия.
Читаемость и надёжность скриптов. Когда каждая страница представлена отдельным Java-файлом, можно легко определить, какие действия выполняются на конкретной странице, просто просматривая соответствующий класс. Если необходимо изменить конкретный участок кода, это можно сделать, не затрагивая другие классы.
Реализация POM в проекте Selenium
Как уже упоминалось, каждый Java-класс будет представлять соответствующую страницу. В этом руководстве будут созданы два файла страниц:
BrowserStackHomePage
BrowserStackSignUpPage
Каждый из этих файлов будет содержать UI-элементы (объекты), которые присутствуют на соответствующих страницах. В них также будут описаны действия, выполняемые с этими элементами.
Пример структуры проекта для POM

Java-файл BrowserStackHomePage

Объяснение кода:
Строки 10-11: Определение элементов, присутствующих на главной странице BrowserStack, таких как заголовок (header) и кнопка “Get Started”.
Строки 17-24: Выполнение действий с указанными объектами на главной странице BrowserStack.
Фрагмент кода:
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackHomePage {
WebDriver driver;
By Header=By.xpath("//h1");
By getStarted=By.xpath("//*[@id='signupModalButton']");
public BrowserStackHomePage(WebDriver driver) {
this.driver=driver;
}
public void veryHeader() {
String getheadertext=driver.findElement(Header).getText();
assertEquals("App & Browser Testing Made Easy", getheadertext);
}
public void clickOnGetStarted() {
driver.findElement(getStarted).click();
}
}
Java-файл BrowserStackSignUpPage:

Объяснение кода:
Строки 10-14: Определение элементов, присутствующих на странице регистрации BrowserStack, таких как заголовок (header) и кнопка “Get Started”.
Строки 20-35: Выполнение действий с указанными объектами на странице регистрации BrowserStack.
Фрагмент кода:
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackSignUpPage {
WebDriver driver;
By Header = By.xpath("//h1");
By userName = By.xpath("//*[@id='user_full_name']");
By businessEmail = By.xpath("//*[@id='user_email_login']");
By password = By.xpath("//*[@id='user_password']");
public BrowserStackSignUpPage(WebDriver driver) {
this.driver = driver;
}
public void veryHeader() {
String getheadertext = driver.findElement(Header).getText().trim();
assertEquals("Create a FREE Account", getheadertext);
}
public void enterFullName(String arg1) {
driver.findElement(userName).sendKeys(arg1);
}
public void enterBusinessEmail(String arg1) {
driver.findElement(businessEmail).sendKeys(arg1);
}
public void enterPasswrod(String arg1) {
driver.findElement(password).sendKeys(arg1);
}
}
Java-файл BrowserStackSetup

Объяснение кода:
Строки 21-27: Настройка браузера и загрузка веб-сайта для выполнения тестовых скриптов.
Строки 29-43: Инициализация объекта WebDriver для BrowserStackHomePage и BrowserStackSignUpPage, а также выполнение действий на этих страницах.
Фрагмент кода:
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
String driverPath = "C:\\geckodriver.exe";
WebDriver driver;
BrowserStackHomePage objBrowserStackHomePage;
BrowserStackSignUpPage objBrowserStackSignUpPage;
@BeforeTest
public void setup() {
System.setProperty("webdriver.chrome.driver", "C:\\BrowserStack\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.browserstack.com/");
}
@Test(priority = 1)
public void navigate_to_homepage_click_on_getstarted() {
objBrowserStackHomePage = new BrowserStackHomePage(driver);
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
}
@Test(priority = 2)
public void enter_userDetails() {
objBrowserStackSignUpPage = new BrowserStackSignUpPage(driver);
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName("TestUser");
objBrowserStackSignUpPage.enterBusinessEmail("TestUser@gmail.com");
objBrowserStackSignUpPage.enterPasswrod("TestUserPassword");
}
}
Изучить синтаксис Java, автотесты для UI и API, а также актуальные фреймворки можно на курсе по автоматизации тестирования на Java для начинающих.
Что такое Page Factory в Selenium?
Page Factory — это механизм, предоставляемый Selenium WebDriver, который упрощает реализацию Page Object Model, автоматизируя инициализацию веб-элементов. В Page Factory тестировщики используют аннотацию @FindBy
. Метод initElements
используется для инициализации веб-элементов.
@FindBy
: Аннотация, используемая в Page Factory для поиска и инициализации веб-элементов с использованием различных локаторов. Пример инициализации элемента с@FindBy
:
@FindBy(id="elementId") WebElement element;
Аналогично,
@FindBy
можно использовать с разными стратегиями поиска элементов. Вот список доступных локаторов:Class Name
CSS Selector
Name
XPath
TagName
LinkText
PartialLinkText
initElements()
:initElements
— это статический метод в классеPage Factory
. С его помощью можно инициализировать все веб-элементы, объявленные с использованием аннотации@FindBy
.Отложенная инициализация:
AjaxElementLocatorFactory
реализует концепцию ленивой загрузки (lazy load) вPage Factory
. Веб-элементы определяются только тогда, когда выполняется операция или действие с ними. Тайм-аут ожидания веб-элемента можно задать для объектного класса с помощьюAjaxElementLocatorFactory
.
Реализация Page Factory в проекте Selenium
В этом разделе будет использован тот же проект, что и для реализации POM. Два файла страниц будут переиспользованы с добавлением реализации Page Factory
:
BrowserStackHomePage
BrowserStackSignUpPage
Каждый из этих файлов будет содержать только UI-элементы или объекты, присутствующие на соответствующих экранах, а также операции, выполняемые с этими элементами.
Пример структуры проекта для Page Factory
Структура проекта останется неизменной, так как используется тот же кодовый базис. Как уже упоминалось, Page Factory
поддерживает паттерн проектирования Page Object Model:

Java-файл BrowserStackHomePage:

Объяснение кода:
Строки 13-17: Определение элементов, присутствующих на главной странице BrowserStack, таких как заголовок (header) и кнопка “Get Started”, с использованием аннотации
@FindBy
из Page Factory.Строки 23-30: Выполнение действий с указанными объектами на главной странице BrowserStack.
Фрагмент кода:
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class BrowserStackHomePage {
WebDriver driver;
@FindBy(xpath = "//h1")
WebElement Header;
@FindBy(xpath = "//*[@id='signupModalButton']")
WebElement getStarted;
public BrowserStackHomePage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void veryHeader() {
String getheadertext = Header.getText();
assertEquals("App & Browser Testing Made Easy", getheadertext);
}
public void clickOnGetStarted() {
getStarted.click();
}
}
Java-файл BrowserStackSignUpPage:

Объяснение кода:
Строки 14-24: Определение элементов на странице регистрации BrowserStack, таких как заголовок (header) и кнопка “Get Started”, с использованием аннотации
@FindBy
из Page Factory.Строки 26-46: Выполнение действий с указанными объектами на странице регистрации BrowserStack.
Фрагмент кода:
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class BrowserStackSignUpPage {
WebDriver driver;
@FindBy(xpath = "//h1")
WebElement Header;
@FindBy(xpath = "//*[@id='user_full_name']")
WebElement userName;
@FindBy(xpath = "//*[@id='user_email_login']")
WebElement businessEmail;
@FindBy(xpath = "//*[@id='user_password']")
WebElement password;
public BrowserStackSignUpPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void veryHeader() {
String getheadertext = Header.getText().trim();
assertEquals("Create a FREE Account", getheadertext);
}
public void enterFullName(String arg1) {
userName.sendKeys(arg1);
}
public void enterBusinessEmail(String arg1) {
businessEmail.sendKeys(arg1);
}
public void enterPasswrod(String arg1) {
password.sendKeys(arg1);
}
}
Java-файл BrowserStackSetup:

Объяснение кода:
Строки 21-27: Настройка браузера и загрузка веб-сайта для выполнения скриптов.
Строки 29-43: Инициализация объектов драйвера для BrowserStackHomePage и BrowserStackSignUpPage, а также выполнение действий на этих страницах.
Фрагмент кода:
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
String driverPath = "C:\\geckodriver.exe";
WebDriver driver;
BrowserStackHomePage objBrowserStackHomePage;
BrowserStackSignUpPage objBrowserStackSignUpPage;
@BeforeTest
public void setup() {
System.setProperty("webdriver.chrome.driver", "C:\\BrowserStack\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.browserstack.com/");
}
@Test(priority = 1)
public void navigate_to_homepage_click_on_getstarted() {
objBrowserStackHomePage = new BrowserStackHomePage(driver);
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
}
@Test(priority = 2)
public void enter_userDetails() {
objBrowserStackSignUpPage = new BrowserStackSignUpPage(driver);
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName("TestUser");
objBrowserStackSignUpPage.enterBusinessEmail("TestUser@gmail.com");
objBrowserStackSignUpPage.enterPasswrod("TestUserPassword");
}
}
Результаты тестов:

Разница между Page Object Model и Page Factory в Selenium
Page Object Model | Page Factory |
Поиск веб-элементов выполняется с использованием | В Page Factory веб-элементы определяются с помощью аннотации |
POM не поддерживает отложенную инициализацию (lazy initialization). | Page Factory поддерживает отложенную инициализацию. |
POM является паттерном проектирования. | Page Factory — это класс, реализующий паттерн Page Object Model. |
В POM каждый объект страницы необходимо инициализировать вручную. | В Page Factory все объекты страниц инициализируются с помощью метода |
Чтобы проверить работу Page Object Model и Page Factory, запустите код. Поскольку эти механизмы играют ключевую роль в Selenium, тестировщики должны уметь применять их эффективно и точно при автоматизации тестирования. Это поможет оптимизировать процесс автоматизированного тестирования и быстрее получать результаты.
Другие паттерны проектирования, используемые в Selenium
Паттерны проектирования в фреймворке автоматизации тестирования играют важную роль. В Selenium применяются различные паттерны, среди которых:
Singleton
Fluent Page Object Model
Factory
Facade
Singleton Pattern. Паттерн Singleton («одиночка») гарантирует, что в системе создаётся не более одного экземпляра класса. Он часто применяется, когда требуется глобальный объект для управления состоянием системы. Например, в Selenium объект WebDriver обычно создаётся как Singleton, так как в рамках тестового запуска должен использоваться единственный экземпляр браузера.
Fluent Page Object Model. Fluent Page Object Model — это расширение Page Object Model, в котором методы вызываются последовательно, по цепочке, образуя плавный интерфейс (fluent interface). Это делает код тестов более читаемым и компактным, так как несколько действий могут быть выполнены в одной строке кода.
Factory Pattern. Паттерн Factory («фабрика») применяется для инкапсуляции логики создания объектов. Он полезен, когда создание объектов требует сложной логики или зависит от условий, требующих разных подклассов. Этот паттерн позволяет инкапсулировать процесс создания объектов, что облегчает его изменение без влияния на остальную часть кода.
Facade Pattern. Паттерн Facade («фасад») предоставляет единый интерфейс для управления сложной системой. Он используется для того, чтобы скрыть сложность системы за единым интерфейсом, что делает её использование удобнее. В Selenium паттерн Facade можно использовать для создания высокоуровневого API взаимодействия с браузером, что упрощает написание тестов и повышает их читаемость и поддерживаемость.
Как Java-тестировщику работать с Git и GitHub?
Поговорим об этом на открытом уроке 13 марта. Познакомимся с основами Git и GitHub, разберём, зачем тестировщику нужны системы контроля версий и как их применять в автоматизированном тестировании на Java. Записаться