В автоматизированном тестировании на JavaScript с использованием Protractor структура кода играет ключевую роль. Организация тестов с применением базовых классов позволяет избежать дублирования кода, упростить поддержку и ускорить создание новых сценариев.
1. Разделение ответственности. Каждый класс должен отвечать за отдельный аспект приложения: работа с конкретной страницей, управление формой, обработка общих элементов интерфейса. Такой подход соответствует паттерну Page Object Model (POM), широко используемому в Protractor.
2. Переиспользуемость. Базовый класс должен содержать методы, которые могут использоваться в нескольких страницах или тестах. Например, методы для клика по элементам, ввода текста, ожидания элементов.
3. Инкапсуляция действий. Скрытие низкоуровневой работы с веб-элементами через публичные методы класса повышает читаемость тестов и упрощает их поддержку.
Базовый класс обычно включает:
by.css,
by.id, by.xpath). Локаторы хранятся как
приватные или защищённые свойства класса.const { element, by, browser } = require('protractor');
class BasePage {
constructor() {
this.loader = element(by.css('.loader'));
this.alert = element(by.css('.alert'));
}
async open(url) {
await browser.get(url);
}
async clickElement(el) {
await browser.wait(() => el.isPresent(), 5000, 'Element not present');
await el.click();
}
async typeText(el, text) {
await browser.wait(() => el.isPresent(), 5000, 'Element not present');
await el.clear();
await el.sendKeys(text);
}
async waitForLoaderToDisappear() {
await browser.wait(async () => !(await this.loader.isPresent()), 10000, 'Loader did not disappear');
}
async getAlertText() {
await browser.wait(() => this.alert.isPresent(), 5000, 'Alert not present');
return await this.alert.getText();
}
}
Общие методы Методы, которые применимы к большинству страниц: открытие URL, клик по элементу, ввод текста, ожидание появления или исчезновения элементов.
Методы ожиданий Использование
browser.wait с условием ожидаемости
(ExpectedConditions) обеспечивает стабильность тестов и
снижает вероятность ошибок из-за асинхронной загрузки страницы.
Базовый класс не содержит специфики конкретной страницы, но позволяет её легко добавлять в дочерних классах.
class LoginPage extends BasePage {
constructor() {
super();
this.usernameField = element(by.id('username'));
this.passwordField = element(by.id('password'));
this.loginButton = element(by.id('loginBtn'));
}
async login(username, password) {
await this.typeText(this.usernameField, username);
await this.typeText(this.passwordField, password);
await this.clickElement(this.loginButton);
await this.waitForLoaderToDisappear();
}
}
LoginPage наследует все методы
BasePage.Стандартная структура файлов выглядит так:
/tests
login.spec.js
dashboard.spec.js
/pages
base.page.js
login.page.js
dashboard.page.js
/utils
wait.util.js
browser.util.js
/pages — классы страниц./tests — файлы с тестами./utils — вспомогательные функции
(например, дополнительные ожидания, работа с браузером).async/await позволяет синхронизировать
действия и предотвращает неожиданные ошибки из-за асинхронного поведения
браузера.async clickVisible(el) {
const EC = protractor.ExpectedConditions;
await browser.wait(EC.visibilityOf(el), 5000);
await el.click();
}
async getText(el) {
await browser.wait(() => el.isPresent(), 5000);
return await el.getText();
}
async selectOption(el, value) {
await el.element(by.cssContainingText('option', value)).click();
}
Использование таких методов во всех страницах позволяет стандартизировать работу с элементами и снизить количество потенциальных ошибок.
Базовые классы в Protractor создают фундамент для устойчивого и масштабируемого тестирования. Грамотно спроектированные методы и структура обеспечивают переиспользуемость кода, упрощают поддержку и делают тесты читаемыми и предсказуемыми.