Page Object Model (POM) — это шаблон проектирования в автоматизации тестирования, который разделяет тесты и логику взаимодействия с элементами страницы. Главная цель POM — сделать тесты более читаемыми, поддерживаемыми и менее зависимыми от изменений интерфейса.
Разделение логики теста и интерфейса страницы Страница представляется отдельным объектом с методами, которые инкапсулируют взаимодействие с элементами. Тесты при этом используют только методы объекта, не обращаясь напрямую к локаторам.
Инкапсуляция локаторов Все селекторы элементов хранятся в классе страницы. При изменении интерфейса необходимо править только Page Object, а тесты остаются неизменными.
Переиспользование кода Методы страницы могут быть использованы в нескольких тестах, что снижает дублирование кода и облегчает поддержку.
Повышение читаемости тестов Тест становится более «читаемым», поскольку описывает действия на уровне бизнес-логики, а не низкоуровневого взаимодействия с элементами.
Класс Page Object обычно содержит:
element(by.css(...)), element(by.id(...)) и
другие стратегии поиска.Пример структуры Page Object на Protractor:
class LoginPage {
constructor() {
this.usernameInput = element(by.id('username'));
this.passwordInput = element(by.id('password'));
this.loginButton = element(by.css('button[type="submit"]'));
this.errorMessage = element(by.css('.error'));
}
async enterUsername(username) {
await this.usernameInput.clear();
await this.usernameInput.sendKeys(username);
}
async enterPassword(password) {
await this.passwordInput.clear();
await this.passwordInput.sendKeys(password);
}
async clickLogin() {
await this.loginButton.click();
}
async getErrorMessage() {
return await this.errorMessage.getText();
}
}
module.exports = new LoginPage();
Тест, использующий Page Object, становится компактным и понятным:
const loginPage = require('../pages/login.page');
describe('Login functionality', () => {
it('should display error for invalid credentials', async () => {
await loginPage.enterUsername('wrongUser');
await loginPage.enterPassword('wrongPass');
await loginPage.clickLogin();
const error = await loginPage.getErrorMessage();
expect(error).toBe('Invalid username or password');
});
});
Ключевое преимущество — тест не содержит информации о локаторах и низкоуровневых действиях, а описывает последовательность шагов логично и читабельно.
Для больших проектов рекомендуется создавать отдельную папку
pages для всех Page Object. Внутри можно разделять страницы
по функциональным областям, например:
/pages
login.page.js
dashboard.page.js
settings.page.js
Тесты при этом располагаются в папке specs или
tests и импортируют только нужные Page Object.
Protractor работает с промисами, поэтому методы Page Object должны
корректно использовать async/await. Это обеспечивает
последовательное выполнение действий и предотвращает ошибки из-за того,
что элемент еще не появился на странице.
Пример с ожиданием видимости элемента:
async clickLogin() {
await browser.wait(protractor.ExpectedConditions.elementToBeClickable(this.loginButton), 5000);
await this.loginButton.click();
}
Использование ожиданий делает тесты более стабильными, особенно на динамически загружаемых страницах.
Page Object Model является стандартом в современном автоматизированном тестировании веб-приложений на Protractor и JavaScript, позволяя строить надежные и поддерживаемые тестовые фреймворки.