Playwright позволяет эффективно тестировать веб-приложения с использованием автоматизированных сценариев. Однако, при сложных тестах, часто возникает необходимость создавать или управлять различными объектами, такими как страницы, формы, пользователи или данные. В таких случаях применение Factory паттерна может значительно упростить и улучшить организацию тестового кода.
Factory паттерн является порождающим паттерном проектирования, который предоставляет интерфейс для создания объектов, не указывая точный класс создаваемого объекта. В контексте автоматизированного тестирования это позволяет создавать тестовые данные и объекты с минимальными усилиями и высокой гибкостью. Вместо того чтобы создавать множество однотипных объектов вручную, можно определить фабрику, которая будет создавать их по необходимости.
В Playwright часто бывает необходимо работать с веб-страницами, элементами или данными формы. Вместо того чтобы в каждом тесте вручную создавать объекты страницы, лучше использовать фабрики для их создания.
Пример фабрики для страницы, которая генерирует объекты
LoginPage:
class LoginPage {
constructor(page) {
this.page = page;
this.usernameInput = page.locator('input[name="username"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
}
async login(username, password) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
class LoginPageFactory {
static create(page) {
return new LoginPage(page);
}
}
module.exports = { LoginPageFactory };
В этом примере фабрика LoginPageFactory отвечает за
создание объекта страницы LoginPage, инкапсулируя в себе
все детали реализации. Это упрощает создание тестов, так как теперь
можно просто использовать фабрику:
const { test, expect } = require('@playwright/test');
const { LoginPageFactory } = require('./factories');
test('Login test', async ({ page }) => {
const loginPage = LoginPageFactory.create(page);
await loginPage.login('user123', 'password123');
expect(await page.locator('h1').textContent()).toBe('Welcome');
});
Фабрики также могут быть полезны для создания тестовых данных, например, для пользователей. В реальных проектах часто нужно тестировать функциональность с различными данными, такими как имена, email, роли и т. д.
Пример фабрики для создания пользователей:
class User {
constructor(username, email, role) {
this.username = username;
this.email = email;
this.role = role;
}
}
class UserFactory {
static createAdmin() {
return new User('admin', 'admin@example.com', 'admin');
}
static createUser() {
return new User('user', 'user@example.com', 'user');
}
static createGuest() {
return new User('guest', 'guest@example.com', 'guest');
}
}
module.exports = { UserFactory };
Теперь в тестах можно использовать фабрику для создания различных типов пользователей:
const { UserFactory } = require('./factories');
test('Admin user test', async () => {
const admin = UserFactory.createAdmin();
// используйте admin в тестах
});
test('Guest user test', async () => {
const guest = UserFactory.createGuest();
// используйте guest в тестах
});
В некоторых случаях тестовые данные могут поступать из внешних источников, таких как базы данных, API или файлы. В этом случае фабрики могут быть использованы для инкапсуляции логики получения данных и создания объектов.
Пример фабрики, которая загружает тестовые данные из JSON файла:
const fs = require('fs');
class UserFactory {
static createFromFile(filePath) {
const data = JSON.parse(fs.readFileSync(filePath));
return new User(data.username, data.email, data.role);
}
}
module.exports = { UserFactory };
В этом примере фабрика загружает данные о пользователе из файла и
создает объект User. Это полезно, если тесты должны
работать с заранее подготовленными данными.
const { UserFactory } = require('./factories');
test('User from file', async () => {
const user = UserFactory.createFromFile('test-data/user.json');
// используйте user в тестах
});
В более сложных сценариях тестирования может потребоваться создание объектов с зависимостями. Например, при тестировании функциональности корзины покупок могут быть необходимы одновременно объекты товаров и корзины. В таких случаях фабрики могут быть использованы для создания сложных объектов с зависимостями.
Пример фабрики для корзины покупок, которая зависит от объектов товаров:
class Product {
constructor(name, price) {
this.name = name;
this.price = price;
}
}
class Cart {
constructor() {
this.products = [];
}
addProduct(product) {
this.products.push(product);
}
getTotalPrice() {
return this.products.reduce((total, product) => total + product.price, 0);
}
}
class CartFactory {
static createWithProducts(productsData) {
const cart = new Cart();
productsData.forEach((data) => {
const product = new Product(data.name, data.price);
cart.addProduct(product);
});
return cart;
}
}
module.exports = { CartFactory };
В этом примере фабрика CartFactory принимает данные о
товарах, создает объекты Product, добавляет их в корзину и
возвращает готовый объект Cart.
const { CartFactory } = require('./factories');
test('Shopping cart test', async () => {
const cart = CartFactory.createWithProducts([
{ name: 'Laptop', price: 1000 },
{ name: 'Headphones', price: 200 }
]);
expect(cart.getTotalPrice()).toBe(1200);
});
Использование Factory паттерна в тестировании с Playwright позволяет создавать гибкие и поддерживаемые тесты. Этот паттерн помогает управлять сложностью, изолировать логику создания объектов и улучшить повторное использование кода. С помощью фабрик можно легко создавать страницы, пользователей, товары, корзины и другие объекты, а также инкапсулировать логику получения и создания тестовых данных из внешних источников.