Playwright Test

Помимо того, что Playwright является инструментом автоматизации браузера, он также поставляется сполноценным фреймворком для тестирования —— Playwright Test。

Playwright Test помогает организовывать тест-кейсы, генерировать отчёты, запускать параллельно, повторять при сбое и обладает всеми возможностями из коробки.

  1. Playwright Test — этовстроенная среда тестирования, не требующая дополнительных зависимостей.
  2. Файл конфигурации позволяет задаватьтаймаут, повторные попытки, отчёты, проекты браузерови т. д.
  3. Тест-кейсы поддерживаютгруппировку, хуки, data-driven。
  4. и обеспечиваютпараллельное выполнение, HTML-отчёты, повторные попытки при сбоеи другие продвинутые возможности.

Обзор тестового фреймворка

  • Интегрированная среда тестирования: поставляется со встроенным тест-раннером, не нужно отдельно устанавливать Jest или Mocha.
  • Встроенная библиотека утверждений: поддерживаетexpectутверждения.
  • Изоляция тестов: каждыйtestпо умолчанию запускается в новом контексте браузера, независимо друг от друга.
  • Богатые возможности: параллельное выполнение, повторные попытки, скриншоты, запись, HTML-отчёты и т. д.

Способ установки:

npm init playwright@latest

Автоматически создавать структуру проекта, включая файл конфигурацииplaywright.config.js。

1. Сведения о файле конфигурации

Playwright Test используетplaywright.config.js(или.ts) в качестве точки входа конфигурации.

// playwright.config.js
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests',         // 测试目录
  timeout: 30 * 1000,         // 单个测试超时时间
  retries: 2,                 // 失败重试次数
  reporter: [['html'], ['list']], // 测试报告类型
  use: {
    headless: true,           // 是否无头模式
    screenshot: 'only-on-failure', // 失败时截图
    video: 'retain-on-failure',    // 失败时保留视频
    baseURL: 'https://example.com', // 基础 URL
  },
  projects: [
    { name: 'Chromium', use: { browserName: 'chromium' } },
    { name: 'Firefox',  use: { browserName: 'firefox' } },
    { name: 'WebKit',   use: { browserName: 'webkit' } },
  ],
});

2. Структура тестового скрипта

Скрипты Playwright Test обычно включают:

1. Импорт библиотеки тестов

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

2. Написание тест-кейсов

test('示例测试', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveTitle('Example Domain');
});

3. Группировка и хуки

  • Используйтеdescribeдля организации тестов
  • ИспользуйтеbeforeEach / afterEachдля настройки и завершения

Написание тест-кейсов

1. test()Использование функций

test('页面标题验证', async ({ page }) => {
  await page.goto('https://playwright.dev');
  await expect(page).toHaveTitle(/Playwright/);
});

2. describe()Группировка

test.describe('用户登录模块', () => {
  test('输入正确账号密码', async ({ page }) => {
    // 登录逻辑...
  });

  test('输入错误密码', async ({ page }) => {
    // 验证错误提示...
  });
});

3. Хуки тестов

test.describe('购物车模块', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('https://example.com/cart');
  });

  test.afterEach(async ({ page }) => {
    await page.screenshot({ path: 'cart.png' });
  });

  test('添加商品', async ({ page }) => {
    await page.click('#add-item');
    await expect(page.locator('#cart-count')).toHaveText('1');
  });
});

4. Подготовка тестовых данных

Поддерживает параметризованные тесты:

const users = [
  { name: 'admin', password: '123456' },
  { name: 'guest', password: 'guest' },
];

for (const user of users) {
  test(`用户 ${user.name} 登录`, async ({ page }) => {
    await page.goto('https://example.com/login');
    await page.fill('#username', user.name);
    await page.fill('#password', user.password);
    await page.click('#submit');
    await expect(page.locator('.welcome')).toBeVisible();
  });
}

Запуск и отчётность

1. Команды выполнения тестов

npx playwright test          # 运行全部测试
npx playwright test login.spec.js   # 运行单个文件
npx playwright test -g "登录"       # 运行指定用例

2. Параллельное тестирование

Playwright по умолчаниюзапускает файлы параллельно, или вы можете указать количество воркеров в файле конфигурации:

npx playwright test --workers=4

3. Генерация отчёта о тестировании

После запуска сгенерируйтеHTML-отчёт:

npx playwright show-report

4. Механизм повторных попыток при сбое

В файле конфигурацииplaywright.config.jsзадайте:

retries: 2

Когда тест завершается неудачей, он автоматически повторяется; это подходит для обработки перемежающихся ошибок.

  1. Playwright Test — этоинтегрированный фреймворк для тестирования, дополнительные зависимости не нужны.
  2. Файл конфигурации позволяет задаватьтаймаут, повторные попытки, отчёты, проекты браузерови т. д.
  3. Тест-кейсы поддерживаютгруппировку, хуки, data-driven。
  4. и обеспечиваютпараллельное выполнение, HTML-отчёты, повторные попытки при сбоеи другие продвинутые возможности.

Полный пример набора тестов

1. Структура проекта

playwright-demo/
├─ playwright.config.ts           # 全局配置(多项目、多浏览器、报告、重试…)
├─ package.json
├─ tests/
│  ├─ auth.setup.ts               # 一次性登录,生成 storageState
│  ├─ smoke/
│  │  └─ home.spec.ts             # 冒烟用例:标题/URL/截图对比
│  └─ e2e/
│     └─ cart.spec.ts             # 端到端:添加购物车、断言、附件、步骤
├─ fixtures/
│  ├─ pages.ts                    # 页面对象(PO)
│  └─ test.extend.ts              # 自定义 fixtures
└─ snapshots/                     # 视觉基线(自动生成)

2. Файл конфигурации (playwright.config.ts)

Пример

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30_000,
  retries: 2,
  workers: 4,
  reporter: [['html', { outputFolder: 'report' }], ['list']],
  forbidOnly: !!process.env.CI,

  // Единое использование по умолчанию (можно переопределить на уровне проекта или теста)
  использовать: {
    baseURL: 'https://demo.playwright.dev',
    headless: true,
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    trace: 'retain-on-failure',
    viewport: { width: 1366, height: 900 },
    locale: 'zh-CN',
  },

  // Несколько проектов: разные браузеры/устройства/состояния входа
  projects: [
    { name: 'Chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'Firefox',  use: { ...devices['Desktop Firefox'] } },
    {
      name: 'Mobile Chrome',
      use: { ...devices['Pixel 7'], headless: истина },
    },
    // Проект с состоянием входа (повторное использование storageState)
    {
      name: 'Chromium Logged-in',
      use: { storageState: 'storageState.json' },
      dependencies: ['setup'], // Зависит от проекта 'setup' для генерации состояния входа
    },
    // Проект setup: запускается один раз для генерации storageState
    {
      name: 'setup',
      testMatch: /auth\.setup\.ts/,
    },
  ],
});

Ключевые моменты:проекты позволяют запускать один и тот же набор тестов в разных браузерах/конфигурациях; параметр use можно переопределить на глобальном уровне/уровне проекта/уровне теста; отчёты и повторные попытки управляются централизованно в конфигурации.

3. Фикстуры и Page Objects

fixtures/test.extend.ts (пользовательские фикстуры + инкапсуляция общих шагов)

Пример

// fixtures/test.extend.ts
import { test as base } from '@playwright/test';
import { HomePage, CartPage } from './pages';

type MyFixtures = {
  home: HomePage;
  cart: CartPage;
};

export const test = base.extend<MyFixtures>({
  home: async ({ page }, use) => {
    const home = new HomePage(page);
    await use(home);
  },
  cart: async ({ page }, use) => {
    const cart = new CartPage(page);
    await use(cart);
  },
});

export { expect } from '@playwright/test';

Добавьте пользовательские фикстуры на основе test.extend(), что позволяет легко напрямую внедрять экземпляры home и cart в любом тест-кейсе.

fixtures/pages.ts (объекты страниц)

Пример

// fixtures/pages.ts
import { Page, expect } from '@playwright/test';

export class HomePage {
  constructor(private page: Page) {}
  async goto() { await this.page.goto('/'); }
  get tryTodoLink() { return this.page.getByRole('link', { name: /ToDo MVC/i }); }
}

export class CartPage {
  constructor(private page: Page) {}
  async goto() { await this.page.goto('/e2e'); } // Предполагается, что существует пример e2e-страницы
  get addFirstItem() { return this.page.getByRole('button', { name: /Add .* #1/i }); }
  get cartCount() { return this.page.locator('[data-test=cart-count]'); }
  async addOne() { await this.addFirstItem.click(); }
  async expectCount(n: number) { await expect(this.cartCount).toHaveText(String(n)); }
}

4. Предварительный вход (сгенерировать storageState один раз)

tests/auth.setup.ts (запускается только в проекте "setup")

Пример

// tests/auth.setup.ts
import { test, expect } from '@playwright/test';

test('создать storageState', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
  // ...Замените на ваш процесс входа...
  // Предположим, что вход выполнен успешно
  await expect(page).toHaveURL(/todomvc/);
  await page.context().storageState({ path: 'storageState.json' });
});

5. Дымовые тесты (Заголовок/URL/Визуальное сравнение)

tests/smoke/home.spec.ts

Пример

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

test.describe('Дымовые - Главная', () => {
  test('заголовок, URL и визуальный снимок', async ({ page }) => {
    await page.goto('https://playwright.dev');
    await expect(page).toHaveTitle(/Playwright/);
    await expect(page).toHaveURL(/playwright\.dev/);

    // Визуальная регрессия (автосоздание/сравнение базового снимка)
    await expect(page).toHaveScreenshot(); // Первый запуск создаёт базовый снимок
  });
});

Для визуального сравнения рекомендуется использовать toHaveScreenshot (предпочтительнее ручного подхода с использованием page.screenshot() + toMatchSnapshot).

6. Сквозные тесты (шаги, вложения, проверки)

tests/e2e/cart.spec.ts

Пример

import { test, expect } from '../../fixtures/test.extend';

test.describe.configure({ mode: 'parallel' });

test.describe('E2E - Корзина', () => {
  test.beforeEach(async ({ home }) => {
    await test.step('Перейти на главную страницу', async () => {
      await home.goto();
    });
  });

  test('Добавить товар в корзину (с вложением и проверкой)', async ({ page, cart }) => {
    await test.step('Перейти на страницу корзины и добавить товар', async () => {
      await cart.goto();
      await cart.addOne();
      await cart.expectCount(1);
    });

    await test.step('Прикрепить отладочную информацию к отчёту', async () => {
      await test.info().attach('state.json', {
        contentType: 'application/json',
        body: Buffer.from(JSON.stringify({ ts: Date.now(), note: 'после добавления' })),
      });
    });

    // Скриншот элемента
    await test.step('Скриншот элемента', async () => {
      const badge = page.locator('[data-test=cart-count]');
      await expect(badge).toBeVisible();
      await expect(badge).toHaveScreenshot(); // Снимок элемента
    });
  });
});

Используйте test.step для иерархической записи шагов, а test.info().attach() — для прикрепления отладочных данных/скриншотов к отчёту для упрощения диагностики; в параллельном режиме можно использовать describe.configure({ mode: 'parallel' }).

7. Запуск и отчётность

Основные команды:

npx playwright test                # 运行全部
npx playwright test tests/e2e      # 运行目录
npx playwright test -g "Cart"      # 按标题过滤
npx playwright test --project="Chromium"   # 指定项目
npx playwright show-report         # 打开HTML报告
npx playwright test --update-snapshots     # 更新视觉基线
npx playwright test --debug        # 调试模式(Inspector)

Для фильтрации в CLI, выбора проекта, просмотра отчётов, обновления снимков и т.д. см. официальную документацию по CLI/Reporting/Snapshot.


Краткий справочник по общим связанным API (Playwright Test)

1. Тесты и группировка

API Назначение
test(name, fn) Определение тестов
test.describe(title, fn) Группировка
test.describe.configure({ mode }) parallel / serial
test.beforeAll/afterAll Хуки before/after на уровне группы
test.beforeEach/afterEach Хуки before/after тест-кейса
test.skip/only/fixme/slow/fail Отметка/управление тест-кейсами

2. Фикстуры и конфигурация

API Назначение
test.extend<Fixtures>(defs) Расширение пользовательских фикстур
test.use(options) Переопределение на уровне тестаuseОпции (такие какstorageState、viewport、localeи т.д.)
defineConfig({...}) Запись в файле конфигурации (testDir、retries、workers、reporter…)
projects Запуск нескольких проектов/браузеров/разных конфигураций
use: { baseURL, trace, video, screenshot, viewport, locale, timezoneId, storageState } Среда выполнения и стратегия захвата

Подробнее о фикстурах / опции use / параметрах конфигурации и проектах см. в официальной документации "Fixtures / Use options / Configuration / Projects". (Playwright)

3. Утверждения (expect)

API Назначение
expect(value).toBe / toEqual / toContain ... Общие утверждения
expect(locator).toHaveText/Value/Attribute Веб-специфичные утверждения (с умным ожиданием)
expect(locator).toBeVisible/Hidden/Enabled/Disabled/Checked Утверждения состояния
expect(page).toHaveTitle/URL Утверждения страницы
`expect(page/locator).toHaveScreenshot([name options])` Сравнение визуальных снимков (рекомендуется)

Рекомендации по утверждениям и визуальным снимкам см. в документации Assertions and Snapshots.(Playwright)

4. Шаги и вложения

API Назначение
test.step(name, fn) Разбивайте тесты на шаги (визуализация в отчёте)
`test.info().attach(name, { path body, contentType })` Прикрепляйте файлы/данные к тестам или шагам (отображается в отчёте)

Вложения также можно применять на уровне шага (см. TestStep / TestStepInfo).(Playwright)

5. Отчётность и CLI

Команда/Конфигурация Назначение
reporter: [['html', { outputFolder }], ['list']] Конфигурация отчёта
npx playwright test --project="Chromium" Выберите проект для запуска
-g "keyword" / --grep / --grep-invert Фильтровать тест-кейсы
--update-snapshots Обновить визуальные эталоны
npx playwright show-report Открыть отчёт

Смотрите официальную документацию для полного списка параметров CLI и Reporter.(Playwright)

Другие расширения