Мультибраузерное тестирование является одной из ключевых задач автоматизации современного веб-приложения. Playwright предоставляет встроенную поддержку нескольких браузеров — Chromium, Firefox и WebKit. Для эффективного управления различными браузерными контекстами и обеспечения гибкости тестовой инфраструктуры используется паттерн Strategy. Он позволяет инкапсулировать логику работы с браузерами и легко переключать их без изменения кода тестов.
Паттерн Strategy предполагает выделение общего интерфейса для выполнения определённой операции и создание нескольких реализаций этого интерфейса. В контексте Playwright:
Преимущества использования Strategy:
Для реализации Strategy создаётся базовый интерфейс
BrowserStrategy. Он описывает минимальный набор
операций:
class BrowserStrategy {
async launch() {
throw new Error('Метод launch() должен быть реализован');
}
async newContext() {
throw new Error('Метод newContext() должен быть реализован');
}
async close() {
throw new Error('Метод close() должен быть реализован');
}
}
Ключевые моменты:
launch() — инициализация браузера.newContext() — создание нового контекста для
теста.close() — завершение работы браузера.Для каждого браузера создаются отдельные классы, наследующиеся от
BrowserStrategy.
ChromiumStrategy:
const { chromium } = require('playwright');
class ChromiumStrategy extends BrowserStrategy {
async launch() {
this.browser = await chromium.launch({ headless: false });
}
async newContext() {
this.context = await this.browser.newContext();
return this.context.newPage();
}
async close() {
await this.browser.close();
}
}
FirefoxStrategy:
const { firefox } = require('playwright');
class FirefoxStrategy extends BrowserStrategy {
async launch() {
this.browser = await firefox.launch({ headless: false });
}
async newContext() {
this.context = await this.browser.newContext();
return this.context.newPage();
}
async close() {
await this.browser.close();
}
}
WebKitStrategy:
const { webkit } = require('playwright');
class WebKitStrategy extends BrowserStrategy {
async launch() {
this.browser = await webkit.launch({ headless: false });
}
async newContext() {
this.context = await this.browser.newContext();
return this.context.newPage();
}
async close() {
await this.browser.close();
}
}
Каждая стратегия инкапсулирует специфические настройки браузера, позволяя тестам оставаться независимыми от реализации.
Контроллер или BrowserContextManager выбирает нужную стратегию и предоставляет тестам готовую страницу:
class BrowserContextManager {
constructor(strategy) {
this.strategy = strategy;
}
async init() {
await this.strategy.launch();
this.page = await this.strategy.newContext();
}
async close() {
await this.strategy.close();
}
getPage() {
return this.page;
}
}
Пример использования с разными браузерами:
(async () => {
const chromiumManager = new BrowserContextManager(new ChromiumStrategy());
await chromiumManager.init();
const page = chromiumManager.getPage();
await page.goto('https://example.com');
console.log(await page.title());
await chromiumManager.close();
})();
Подобная структура позволяет легко подменять браузер, не изменяя тестовую логику.
Для Playwright-тестов с Jest, Mocha или Playwright Test можно использовать фабрику стратегий:
function getBrowserStrategy(browserName) {
switch (browserName) {
case 'chromium': return new ChromiumStrategy();
case 'firefox': return new FirefoxStrategy();
case 'webkit': return new WebKitStrategy();
default: throw new Error(`Неизвестный браузер: ${browserName}`);
}
}
// Пример конфигурации Playwright Test
const browserManager = new BrowserContextManager(getBrowserStrategy(process.env.BROWSER));
beforeAll(async () => {
await browserManager.init();
});
afterAll(async () => {
await browserManager.close();
});
test('Заголовок страницы', async () => {
const page = browserManager.getPage();
await page.goto('https://example.com');
expect(await page.title()).toBe('Example Domain');
});
Strategy паттерн легко расширяется для:
viewport, geolocation,
permissions).Пример добавления пользовательских настроек:
class ChromiumStrategy extends BrowserStrategy {
constructor(options = {}) {
super();
this.options = options;
}
async launch() {
this.browser = await chromium.launch(this.options);
}
}
Теперь можно создавать инстанс с разными параметрами:
const headlessChromium = new ChromiumStrategy({ headless: true });
const fullChromium = new ChromiumStrategy({ headless: false });
Использование Strategy паттерна при мультибраузерном тестировании в Playwright:
Такой подход является стандартом для масштабируемых проектов с необходимостью тестирования нескольких браузеров одновременно.