Что такое паттерн Page Object?

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

Ответ

Page Object (PO) — это ключевой паттерн проектирования в автоматизации UI-тестирования, который инкапсулирует структуру и поведение веб-страницы (или её компонента) в отдельный класс. Каждый такой класс содержит локаторы элементов и методы для взаимодействия с ними, отделяя тестовую логику от деталей реализации страницы.

Основные преимущества с точки зрения QA:

  • Повышение сопровождаемости: При изменении верстки (например, ID элемента) правки вносятся только в один класс Page Object, а не во все тесты.
  • Улучшение читаемости: Тестовые сценарии становятся лаконичными и понятными, так как используют высокоуровневые методы вроде loginPage.login("user", "pass").
  • Устранение дублирования кода: Логика работы со страницей выносится в одно место.
  • Упрощение повторного использования: Компоненты (например, хедер или футер) можно вынести в отдельные Page Object и использовать на разных страницах.

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

public class LoginPage {
    private WebDriver driver;

    // Локаторы элементов страницы
    private By usernameField = By.id("username");
    private By passwordField = By.id("password");
    private By loginButton = By.id("loginBtn");
    private By errorMessage = By.cssSelector(".alert.error");

    public LoginPage(WebDriver driver) {
        this.driver = driver;
    }

    // Метод для выполнения входа
    public HomePage loginWithValidCredentials(String username, String password) {
        driver.findElement(usernameField).sendKeys(username);
        driver.findElement(passwordField).sendKeys(password);
        driver.findElement(loginButton).click();
        return new HomePage(driver); // Возвращаем Page Object следующей страницы
    }

    // Метод для негативного теста
    public String loginWithInvalidCredentials(String username, String password) {
        driver.findElement(usernameField).sendKeys(username);
        driver.findElement(passwordField).sendKeys(password);
        driver.findElement(loginButton).click();
        return driver.findElement(errorMessage).getText(); // Возвращаем текст ошибки
    }
}

Использование в тесте (JUnit):

@Test
public void successfulLoginTest() {
    LoginPage loginPage = new LoginPage(driver);
    HomePage homePage = loginPage.loginWithValidCredentials("testUser", "testPass");
    assertTrue(homePage.isUserMenuDisplayed());
}