Фикстуры Playwright и параметризация

В этой главе рассказывается о механизме фикстур Playwright, о том, как создавать собственные фикстуры, и о приёмах параметризованного тестирования.


Что такое фикстура

Фикстура — это механизм внедрения зависимостей для параметров тестовых функций Playwright.

Каждый тест получает необходимые фикстуры путём деструктуризации параметров (например,{ page }), а Playwright управляет созданием и очисткой.

Пример

// page и context — встроенные фикстуры
test('Использование встроенных фикстур', async ({ page, context }) => {
  // Playwright автоматически создаёт page и context
  // Автоматически очищается после завершения теста
  await page.goto('https://www.example.com/');
});

Краткий справочник по встроенным фикстурам

ФикстураTypeОписание
pagePageНезависимая вкладка браузера
contextBrowserContextКонтекст браузера
browserБраузерЭкземпляр браузера
browserNamestringИмя текущего браузера
requestAPIRequestContextКлиент HTTP-запросов

Пользовательские фикстуры

Черезtest.extend()Создавайте пользовательские фикстуры, чтобы внедрять дополнительные зависимости или переопределять встроенные фикстуры.

Пример

// Путь к файлу: tests/fixtures.ts
import { test as base, expect } from '@playwright/test';

// Определите тип пользовательской фикстуры
type MyFixtures = {
  todoPage: { goto: () => Promise<void>; addTodo: (text: string) => Promise<void> };
  authenticatedPage: any;
};

export const test = base.extend<MyFixtures>({
  // Пользовательская фикстура: объект страницы Todo
  todoPage: async ({ page }, use) => {
    // Создать
    const todoPage = {
      goto: async () => {
        await page.goto('https://demo.playwright.dev/todomvc');
      },
      addTodo: async (text: string) => {
        await page.getByPlaceholder('Что нужно сделать?').fill(text);
        await page.keyboard.press('Enter');
      },
    };
    // Внедрить в тест
    await use(todoPage);
    // Логика очистки (при необходимости)
  },

  // Пользовательская фикстура: аутентифицированная страница
  authenticatedPage: async ({ browser }, use) => {
    const context = await browser.newContext({
      storageState: 'playwright/.auth/user.json',
    });
    const page = await context.newPage();
    await use(page);
    await context.close();
  },
});

export { expect };

Использование пользовательских фикстур

Пример

// Путь к файлу: tests/todo.spec.ts
import { test, expect } from './fixtures';

test('Add Todo', async ({ todoPage }) => {
  await todoPage.goto();
  await todoPage.addTodo('Learn Playwright');
  await todoPage.addTodo('Master Fixtures');
  // Проверить...
});

Области действия фикстур

Фикстуры имеют три области действия, управляемые с помощьюscopeпараметр.

Область действияЗначениеЖизненный цикл
Уровень теста (по умолчанию)scope: 'test'Создаётся один раз для каждого теста
Уровень воркераscope: 'worker'Создаётся один раз для каждого процесса воркера и используется всеми тестами в одном воркере

Пример

// Фикстура уровня воркера (общая для всех тестов в одном воркере)
const test = base.extend({
  sharedResource: [async ({}, use) => {
    const resource = await createExpensiveResource();
    await use(resource);
    await resource.dispose();
  }, { scope: 'worker' }],  // Обратите внимание на синтаксис массива
});

Фикстуры уровня Worker являются общими для нескольких тестов в рамках одного процесса Worker и подходят для ресурсов с высокими накладными расходами на создание, таких как подключения к базе данных.


Переопределение встроенных фикстур

Вы можете переопределить встроенные фикстуры, чтобы изменить поведение по умолчанию.

Пример

const test = base.extend({
  // Переопределите встроенную фикстуру page, чтобы изменить область просмотра по умолчанию
  page: async ({ baseURL, page }, use) => {
    await page.setViewportSize({ width: 1920, height: 1080 });
    await use(page);
  },

  // Переопределить storageState
  storageState: 'playwright/.auth/admin.json',
});

Автоматическая очистка фикстуры

Логика очистки фикстуры выполняется послеuse()вызова, аналогично эффектуafterEach.

Пример

const test = base.extend({
  tempUser: async ({ request }, use) => {
    // Создать временного пользователя
    const resp = await request.post('/api/users', {
      data: { name: 'temp_' + Date.now() },
    });
    const user = await resp.json();

    // Внедрить в тест
    await use(user);

    // Автоматическая очистка: удалить временного пользователя
    await request.delete(`/api/users/${user.id}`);
  },
});

Параметризованные тесты

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

Пример

// Тест, управляемый данными
const testCases = [
  { username: 'admin', password: 'admin123', expected: 'Панель управления' },
  { username: 'user',  password: 'user123',  expected: 'Личный кабинет' },
  { username: 'guest', password: 'guest123', expected: 'Страница посетителя' },
];

for (const { username, password, expected } of testCases) {
  test(`Пользователь ${username}видит $ после входа в систему{expected}`, async ({ page }) => {
    await page.goto('/login');
    await page.getByLabel('Username').fill(username);
    await page.getByLabel('Password').fill(password);
    await page.getByRole('button', { name: 'Login' }).click();
    await expect(page.getByText(expected)).toBeVisible();
  });
}

Аннотации тестов

Аннотации используются для добавления метаданных к тестам, которые можно просматривать и фильтровать в репортере.

Пример

test('Тест с аннотацией', async ({ page }) => {
  // Добавить аннотацию (внутри тела тестовой функции)
  test.info().annotations.push({
    type: 'issue',
    description: 'https://github.com/example/bug/123',
  });
  test.info().annotations.push({
    type: 'description',
    description: 'Этот тест покрывает все ветки процесса входа',
  });

  // Логика теста...
});

// Использование тега (в имени теста)
test('Быстрый дымовой тест @smoke @critical', async ({ page }) => {
  // Вы можете запустить только этот тест с помощью npx playwright test --grep "@smoke"
});
Другие расширения