Миграция с Cypress

При переходе с Cypress на Playwright важно учитывать структурные и концептуальные различия между этими инструментами. Playwright предоставляет более гибкий API, поддерживает несколько браузеров и обеспечивает возможность параллельного запуска тестов без глобальных ограничений, с которыми сталкивается Cypress.


1. Установка и базовая конфигурация

В Playwright установка выполняется через npm:

npm install -D @playwright/test
npx playwright install

После установки создается базовая структура проекта с тестами, конфигурацией и скриншотами:

npx playwright init

Конфигурационный файл playwright.config.js позволяет настраивать браузеры, репортеры, таймауты и параметры запуска:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  timeout: 30000,
  use: {
    headless: true,
    viewport: { width: 1280, height: 720 },
    actionTimeout: 5000,
    trace: 'on-first-retry',
  },
  projects: [
    { name: 'Chromium', use: { browserName: 'chromium' } },
    { name: 'Firefox', use: { browserName: 'firefox' } },
    { name: 'WebKit', use: { browserName: 'webkit' } },
  ],
});

Ключевой момент: Playwright сразу поддерживает несколько браузеров и отдельные проекты для них, что является преимуществом перед Cypress.


2. Структура теста

Cypress использует глобальные объекты cy и команды, а Playwright опирается на объекты page и browserContext. Пример простого теста на Playwright:

import { test, expect } from '@playwright/test';

test('Проверка заголовка страницы', async ({ page }) => {
  await page.goto('https://example.com');
  const title = await page.title();
  expect(title).toBe('Example Domain');
});

Сравнение с Cypress:

cy.visit('https://example.com');
cy.title().should('eq', 'Example Domain');

Отличие: Playwright требует явного получения объекта page, что обеспечивает больший контроль над сессиями и контекстами.


3. Работа с элементами

В Cypress команды встроены в цепочку, а Playwright использует асинхронные методы:

await page.locator('text=Войти').click();
await page.locator('#username').fill('admin');
await page.locator('#password').fill('password');
await page.locator('button[type="submit"]').click();

Совет по миграции:

  • Cypress: cy.get(selector).type('text')
  • Playwright: await page.locator(selector).fill('text')

locator в Playwright позволяет повторно использовать селекторы и ждать готовности элементов без дополнительного кода.


4. Асинхронность и ожидания

Cypress автоматически ждёт элементы, Playwright требует явного ожидания или использования встроенных методов ожидания:

await page.locator('#success-message').waitFor({ state: 'visible' });

Замена cy.wait() из Cypress:

  • Cypress: cy.wait(1000)
  • Playwright: использовать await page.waitForTimeout(1000) или лучше — waitForSelector/locator.waitFor, чтобы избежать фиксированных задержек.

5. Тестовые сценарии и структуры

Playwright поддерживает структуру, похожую на Jest:

test.describe('Форма логина', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('https://example.com/login');
  });

  test('Ввод корректных данных', async ({ page }) => {
    await page.locator('#username').fill('admin');
    await page.locator('#password').fill('password');
    await page.locator('button[type="submit"]').click();
    await expect(page.locator('#welcome')).toHaveText('Добро пожаловать, admin!');
  });
});

Сравнение: Cypress использует describe и it, но глобальный объект cy позволяет проще писать цепочки команд. В Playwright цепочки заменяются на асинхронные вызовы через await.


6. Снимки и скриншоты

Playwright предоставляет встроенные методы для скриншотов и записи видео:

await page.screenshot({ path: 'screenshot.png', fullPage: true });

Для записи видео:

import { test } from '@playwright/test';

test('Тест с видео', async ({ page }) => {
  await page.context().tracing.start({ screenshots: true, snapshots: true });
  await page.goto('https://example.com');
  await page.context().tracing.stop({ path: 'trace.zip' });
});

Cypress также поддерживает скриншоты, но Playwright даёт гибкий контроль над всеми этапами теста и контекстами браузеров.


7. Мокирование и перехват запросов

Cypress использует cy.intercept(), Playwright — route и request interception:

await page.route('**/api/data', route => {
  route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ success: true }),
  });
});
await page.goto('https://example.com');

Преимущество: Возможность точечно подменять ответы, контролировать все запросы и создавать разные сценарии без внешних библиотек.


8. Параллельный запуск и контексты

Playwright позволяет создавать отдельные контексты для тестов, что эквивалентно изоляции:

const context = await browser.newContext();
const page = await context.newPage();

Это упрощает параллельный запуск и избегает побочных эффектов между тестами, что сложнее реализовать в Cypress.


9. Репортеры и интеграции

Playwright поддерживает репортеры:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [['list'], ['html', { outputFolder: 'playwright-report' }]],
});

HTML-репорты, Allure и интеграция с CI/CD полностью аналогичны Cypress, но с большей гибкостью в настройке и параллельных сборках.


10. Рекомендации при миграции

  • Проверять асинхронность: Cypress часто скрывает ожидания, в Playwright их нужно контролировать.
  • Переписывать цепочки команд: cy.get(...).click()await page.locator(...).click()
  • Использовать locator вместо прямого селектора: это снижает риск flaky-тестов.
  • Создавать отдельные браузерные контексты для каждого теста: обеспечивает чистую среду.
  • Мигрировать мокирование: cy.intercept()page.route().
  • Обновлять CI/CD скрипты: Playwright имеет свои команды запуска и отчётности.

Playwright обеспечивает более глубокий контроль над браузером, изоляцию тестов и полноценную поддержку нескольких браузеров, что делает миграцию с Cypress стратегически выгодной для проектов с высокими требованиями к стабильности и параллелизации.