Что такое Page Factory в контексте Selenium?

«Что такое Page Factory в контексте Selenium?» — вопрос из категории Selenium и Selenide, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Page Factory — это встроенный в Selenium WebDriver паттерн проектирования (реализация Page Object), который использует аннотации @FindBy для декларативного описания веб-элементов и метод PageFactory.initElements() для их "ленивой" инициализации.

Основная цель: Уменьшение boilerplate-кода и повышение читаемости Page Object-классов.

Пример реализации на Java:

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

public class LoginPage {
    // Элементы объявляются с аннотацией @FindBy
    @FindBy(id = "username")
    private WebElement usernameField;

    @FindBy(name = "password")
    private WebElement passwordField;

    @FindBy(css = "button[type='submit']")
    private WebElement loginButton;

    @FindBy(className = "error-message")
    private WebElement errorMessage;

    // Конструктор инициализирует все элементы
    public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    // Методы страницы
    public void login(String user, String pass) {
        usernameField.sendKeys(user);
        passwordField.sendKeys(pass);
        loginButton.click();
    }

    public String getErrorMessage() {
        return errorMessage.getText();
    }
}

Преимущества с точки зрения тестирования:

  • Ленивая загрузка (Lazy Load): Элементы ищутся в DOM только при первом обращении к ним (например, при вызове sendKeys()), а не в момент вызова initElements. Это ускоряет инициализацию страницы.
  • Читаемость и поддержка: Локаторы собраны в одном месте вверху класса.
  • Сокращение кода: Не нужно писать driver.findElement(By.id(...)) для каждого элемента.

Недостатки и подводные камни:

  • StaleElementReferenceException: Поскольку элементы кэшируются после первой находки, при обновлении DOM (AJAX, SPA) ссылка может устареть. Решение — использовать PageFactory.initElements повторно или обновлять элементы в методах.
  • Меньшая гибкость: Сложнее работать с динамическими локаторами, которые вычисляются во время выполнения.