Page Object Model (POM) — один из первых архитектурных паттернов, с которым сталкивается новичок в автоматизации тестирования, и один из самых частых вопросов на собеседовании на позицию QA-automation. Идея простая: вместо того чтобы в каждом тесте заново искать элементы страницы и описывать действия с ними, вы один раз описываете страницу как отдельный объект — а тесты просто используют его методы.
Проблема, которую решает POM
Без паттерна тесты быстро превращаются в дублирующийся код: локаторы полей логина, кнопки входа и текста ошибки копируются в каждый тест, который взаимодействует со страницей авторизации. Стоит вёрстке немного измениться — и приходится править локатор в десятке мест одновременно.
В примерах ниже для краткости опущены строки import { test, expect } from '@playwright/test' и import { LoginPage } from './login.page.js' — в реальном файле теста они обязательны.
// Без Page Object — локаторы дублируются в каждом тесте
test('успешный вход', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Пароль').fill('password123');
await page.getByRole('button', { name: 'Войти' }).click();
});
test('ошибка при неверном пароле', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Пароль').fill('wrong');
await page.getByRole('button', { name: 'Войти' }).click();
await expect(page.getByText('Неверный пароль')).toBeVisible();
});
В примерах ниже для краткости опущены строки import { test, expect } from '@playwright/test' и import { LoginPage } from './login.page.js' — в реальном файле теста они обязательны.
// Без Page Object — локаторы дублируются в каждом тесте
test('успешный вход', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Пароль').fill('password123');
await page.getByRole('button', { name: 'Войти' }).click();
});
test('ошибка при неверном пароле', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Пароль').fill('wrong');
await page.getByRole('button', { name: 'Войти' }).click();
await expect(page.getByText('Неверный пароль')).toBeVisible();
});
Как выглядит с Page Object Model
Локаторы и действия со страницей выносятся в отдельный класс — «объект страницы»:
// login.page.js — объект страницы логина
class LoginPage {
constructor(page) {
this.page = page;
this.emailInput = page.getByLabel('Email');
this.passwordInput = page.getByLabel('Пароль');
this.loginButton = page.getByRole('button', { name: 'Войти' });
}
async goto() {
await this.page.goto('/login');
}
async login(email, password) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}
// login.page.js — объект страницы логина
class LoginPage {
constructor(page) {
this.page = page;
this.emailInput = page.getByLabel('Email');
this.passwordInput = page.getByLabel('Пароль');
this.loginButton = page.getByRole('button', { name: 'Войти' });
}
async goto() {
await this.page.goto('/login');
}
async login(email, password) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}
Теперь тесты используют объект страницы, а не сырые локаторы:
test('успешный вход', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'password123');
await expect(page).toHaveURL('/dashboard');
});
test('ошибка при неверном пароле', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'wrong');
await expect(page.getByText('Неверный пароль')).toBeVisible();
});
test('успешный вход', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'password123');
await expect(page).toHaveURL('/dashboard');
});
test('ошибка при неверном пароле', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'wrong');
await expect(page.getByText('Неверный пароль')).toBeVisible();
});
Если вёрстка изменится — например, поменяется способ поиска кнопки — править нужно в одном месте, внутри класса LoginPage, а не в каждом тесте, который использует страницу логина.
Почему это спрашивают на собеседовании
POM — это не специфика конкретного инструмента (Playwright, Selenium, Cypress), а общий архитектурный принцип автоматизации, применимый практически в любом фреймворке. Интервьюер, спрашивая про Page Object Model, проверяет не знание синтаксиса, а понимание того, зачем вообще нужна архитектура в тестах, а не просто «код, который работает».
Частые вопросы про Page Object Model
Обязательно ли использовать Page Object Model в автотестах? Формально нет, но на любом проекте с несколькими десятками тестов без POM код быстро становится трудно поддерживать — дублирование локаторов превращается в реальную проблему при любом изменении вёрстки.
Чем Page Object Model отличается просто от вынесения локаторов в отдельный файл? POM — это не просто хранилище локаторов, а объект с методами, описывающими действия на странице (login(), search()) — тест работает через эти методы, а не напрямую с локаторами. Это делает тесты читаемыми на уровне бизнес-логики, а не технических деталей взаимодействия со страницей.
Нужно ли знать POM для позиции Junior QA-automation? Да, это один из базовых архитектурных паттернов, который спрашивают даже на начальных позициях — не в деталях реализации, а на уровне понимания идеи и того, зачем он нужен.
Есть ли альтернативы Page Object Model? Да, существуют более новые подходы вроде Screenplay Pattern, но POM остаётся самым распространённым и понятным для входа паттерном, с которого логично начинать изучение архитектуры автотестов.
Чем Page Object Model отличается просто от вынесения локаторов в отдельный файл? POM — это не просто хранилище локаторов, а объект с методами, описывающими действия на странице (login(), search()) — тест работает через эти методы, а не напрямую с локаторами. Это делает тесты читаемыми на уровне бизнес-логики, а не технических деталей взаимодействия со страницей.
Нужно ли знать POM для позиции Junior QA-automation? Да, это один из базовых архитектурных паттернов, который спрашивают даже на начальных позициях — не в деталях реализации, а на уровне понимания идеи и того, зачем он нужен.
Есть ли альтернативы Page Object Model? Да, существуют более новые подходы вроде Screenplay Pattern, но POM остаётся самым распространённым и понятным для входа паттерном, с которого логично начинать изучение архитектуры автотестов.
Закрепить Page Object Model на практике
Понять идею POM на словах — одно, а написать архитектуру автотестов с нуля — другое. Потренироваться можно на бесплатном тренажёре Playwright Arena от Quality Academy — 30 задач в трёх модулях, без оплаты.
-------
Полезные ссылки школы
Сайт Quality Academy:
https://quality-academy.ru/main
Telegram-канал:
https://t.me/quality_academy
YouTube-канал:
https://www.youtube.com/@quality_academy
ВКонтакте:
https://vk.com/quality_academy
Канал отзывов учеников (58+ отзывов):
https://t.me/quality_academy_reviews
Задать вопрос менеджеру:
https://t.me/quality_academy_bot
Тест «Подойдёт ли вам тестирование»:
https://quiz.quality-academy.ru
5000+ вопросов с собесов тестировщика — бот-тренажёр:
https://t.me/quality_academy_interview_bot
3 практические задачи и дорожная карта:
https://t.me/quality_academy_tasks_bot
Бесплатные тренажёры — SQL Arena, Playwright Arena, Python Arena:
SQL Arena · Playwright Arena · Python Arena
https://quality-academy.ru/main
Telegram-канал:
https://t.me/quality_academy
YouTube-канал:
https://www.youtube.com/@quality_academy
ВКонтакте:
https://vk.com/quality_academy
Канал отзывов учеников (58+ отзывов):
https://t.me/quality_academy_reviews
Задать вопрос менеджеру:
https://t.me/quality_academy_bot
Тест «Подойдёт ли вам тестирование»:
https://quiz.quality-academy.ru
5000+ вопросов с собесов тестировщика — бот-тренажёр:
https://t.me/quality_academy_interview_bot
3 практические задачи и дорожная карта:
https://t.me/quality_academy_tasks_bot
Бесплатные тренажёры — SQL Arena, Playwright Arena, Python Arena:
SQL Arena · Playwright Arena · Python Arena