WebdriverIO — это мощный инструмент для автоматизации тестирования веб-приложений на JavaScript. Одним из ключевых аспектов эффективной разработки тестов является организация кода таким образом, чтобы минимизировать дублирование и облегчить поддержку. Для этого активно используются механизмы наследования и переиспользования кода.
В WebdriverIO тестовые сценарии часто строятся на основе классов. Использование классов позволяет создавать структурированные объекты страниц (Page Objects), которые инкапсулируют элементы и методы взаимодействия с ними.
class BasePage {
open(path) {
return browser.url(path);
}
waitForElement(element, timeout = 5000) {
element.waitForDisplayed({ timeout });
}
}
class LoginPage extends BasePage {
get usernameInput() { return $('#username'); }
get passwordInput() { return $('#password'); }
get loginButton() { return $('#login'); }
login(username, password) {
this.usernameInput.setValue(username);
this.passwordInput.setValue(password);
this.loginButton.click();
}
}
Ключевые моменты:
BasePage содержит общие методы, применимые ко всем
страницам.LoginPage наследует функционал BasePage,
не дублируя методы open или
waitForElement.Page Object Model (POM) является стандартом для организации тестов WebdriverIO. Каждая страница представляется отдельным классом с методами взаимодействия.
Пример использования наследования в POM:
class ProductPage extends BasePage {
get addToCartButton() { return $('#add-to-cart'); }
get productTitle() { return $('h1.product-title'); }
addProductToCart() {
this.waitForElement(this.addToCartButton);
this.addToCartButton.click();
}
}
class SpecialProductPage extends ProductPage {
get specialOfferBanner() { return $('#special-offer'); }
verifySpecialOffer() {
this.waitForElement(this.specialOfferBanner);
return this.specialOfferBanner.isDisplayed();
}
}
Пояснения:
SpecialProductPage расширяет ProductPage,
переиспользуя методы добавления товара в корзину.verifySpecialOffer)
добавляется без изменения базового класса.Помимо Page Objects, переиспользование кода достигается через модульные функции и вспомогательные утилиты.
// utils/wait.js
function waitForVisible(element, timeout = 5000) {
element.waitForDisplayed({ timeout });
}
function waitForClickable(element, timeout = 5000) {
element.waitForClickable({ timeout });
}
module.exports = { waitForVisible, waitForClickable };
// В тесте
const { waitForVisible, waitForClickable } = require('./utils/wait');
describe('Cart tests', () => {
it('should add product to cart', () => {
const productPage = new ProductPage();
productPage.open('/product/1');
waitForVisible(productPage.addToCartButton);
waitForClickable(productPage.addToCartButton);
productPage.addProductToCart();
});
});
Преимущества подхода:
Для дополнительного переиспользования иногда применяются миксины — объекты с методами, которые можно включать в класс.
const LoggingMixin = Base => class extends Base {
logAction(action) {
console.log(`Action performed: ${action}`);
}
};
class CheckoutPage extends LoggingMixin(BasePage) {
get checkoutButton() { return $('#checkout'); }
proceedToCheckout() {
this.logAction('Proceeding to checkout');
this.checkoutButton.click();
}
}
Особенности:
Использование наследования и переиспользования кода позволяет выстраивать многоуровневую архитектуру тестов:
Такой подход снижает количество дублируемого кода и облегчает масштабирование автоматизации.
Применение наследования и утилит полностью соответствует принципу DRY:
BasePage или утилитах
(utils).Этот подход к организации тестов в WebdriverIO делает код структурированным, масштабируемым и удобным для поддержки, позволяя создавать сложные автоматизированные сценарии без излишнего дублирования и хаоса в кодовой базе.