Основная конфигурация

Урок: Основная конфигурация Playwright Test

Введение

Когда человек только начинает писать тесты на Playwright, он часто думает, что главное — это сами spec-файлы. Кажется, что вся работа происходит именно там: открыл страницу, кликнул кнопку, проверил текст. Но довольно быстро выясняется, что одних тестов недостаточно.

Представь, что у тебя есть команда курьеров. Каждый день им нужно объяснять одно и то же: откуда забирать заказ, по какому маршруту ехать, что делать при проблемах, как отмечать результат. Если каждому курьеру рассказывать это отдельно, начнется путаница. Гораздо удобнее один раз задать общие правила, а дальше все работают по ним.

Конфигурация Playwright Test — это как раз такое место с общими правилами для тестового проекта. В ней мы задаем, где лежат тесты, в каких браузерах их запускать, какой адрес сайта считать базовым, сколько раз повторять упавшие тесты, какой отчет строить после запуска и нужно ли поднимать локальный сервер перед тестами. Именно файл playwright.config Playwright использует как центральную точку настройки тестового раннера. (playwright.dev)

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

Что такое файл конфигурации и зачем он нужен

В Playwright основная конфигурация обычно находится в файле playwright.config.ts. Документация прямо показывает, что именно этот файл используется для настроек запуска: каталог тестов, параллельность, повторы, репортеры, use-опции, проекты и webServer. (playwright.dev)

На практике это означает простую вещь: тесты описывают поведение, а конфигурация описывает условия, в которых эти тесты выполняются.

Например:

  • тесты лежат в папке tests;
  • запускать их нужно в Chromium и Firefox;
  • сайт открывается по адресу http://localhost:3000;
  • при падении на CI тест можно повторить;
  • перед запуском надо поднять локальное приложение.

Все это — не логика конкретного теста, а общие правила проекта. Поэтому им и место в конфигурации.

Обычно файл начинается так:

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

export default defineConfig({
  testDir: './tests',
});

Здесь есть две важные детали.

defineConfig(...) — это специальная функция Playwright для описания конфигурации. Она помогает оформить настройки аккуратно и с подсказками типов в TypeScript.

export default — это экспорт конфигурации по умолчанию. Так Playwright может прочитать этот объект и использовать его при запуске тестов.

Пока настройка совсем маленькая: мы просто говорим, что тесты лежат в папке tests. Но дальше этот объект можно постепенно расширять.

Базовая структура конфигурации

Посмотрим на типичный учебный пример:

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

export default defineConfig({
  testDir: './tests',
  timeout: 30_000,
  expect: {
    timeout: 5_000,
  },
  fullyParallel: true,
  retries: 0,
  reporter: 'html',

  use: {
    baseURL: 'http://localhost:3000',
    headless: true,
    screenshot: 'only-on-failure',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

На первый взгляд настроек много, но они делятся на понятные группы.

Сверху находятся настройки самого тестового раннера: где искать тесты, сколько времени ждать, запускать ли файлы параллельно, сколько делать повторов, какой использовать репортер. Документация отдельно подчеркивает, что runner options — это верхнеуровневые настройки, и их не нужно помещать внутрь use. (playwright.dev)

А вот внутри use находятся настройки окружения выполнения теста: базовый URL, режим headless, скриншоты, trace и другие TestOptions. Именно туда обычно попадают параметры, которые относятся к браузеру, контексту или странице. (playwright.dev)

Это разделение очень важно понять с самого начала. Частая ошибка новичка — складывать все подряд в use. Но логика тут простая:

  • если настройка относится к тому, как запускается раннер, она обычно идет наверх;
  • если настройка относится к тому, в каких условиях работает браузерный тест, она обычно идет в use.

Настройка testDir: где Playwright ищет тесты

Одна из самых простых и понятных настроек — testDir.

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

export default defineConfig({
  testDir: './tests',
});

Эта настройка говорит Playwright, в какой папке искать тестовые файлы. По документации это один из базовых параметров конфигурации. (playwright.dev)

Что происходит на практике:

  • ты запускаешь npx playwright test;
  • Playwright смотрит в playwright.config.ts;
  • берет значение testDir;
  • ищет тесты в указанной директории.

Если проект маленький, это кажется мелочью. Но когда папок становится больше, явная настройка testDir помогает держать структуру проекта под контролем.

Таймауты: сколько ждать тест и проверку

В реальном UI-тестировании все не происходит мгновенно. Страница загружается, данные приходят по сети, кнопки становятся доступными не сразу. Поэтому у тестов всегда есть тема ожиданий и времени.

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

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

export default defineConfig({
  timeout: 30_000,
  expect: {
    timeout: 5_000,
  },
});

timeout — это общий лимит времени на один тест. Если тест выполняется слишком долго, Playwright остановит его.

expect.timeout — это лимит времени для ожиданий expect. Например, когда мы ждем, что элемент появится на странице.

Смысл здесь такой: тесту можно дать, например, 30 секунд на весь сценарий, а отдельной проверке — только 5 секунд. Это помогает быстрее понимать, что именно пошло не так: завис весь тест или не выполнилось конкретное ожидание.

use: общие настройки для страницы и браузерного контекста

Раздел use — один из самых важных в конфигурации. Документация описывает его как место, где задаются test options, и показывает, что эти настройки можно задавать глобально, переопределять на уровне проекта и даже на уровне отдельного теста через test.use(). (playwright.dev)

Пример:

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

export default defineConfig({
  use: {
    baseURL: 'http://localhost:3000',
    headless: true,
    viewport: { width: 1280, height: 720 },
    screenshot: 'only-on-failure',
  },
});

Разберем по частям.

baseURL — базовый адрес приложения. Благодаря ему можно писать не полный URL, а короткий путь.

headless: true — браузер запускается без видимого окна. Это удобно для автоматического запуска и CI.

viewport — размер окна браузера. Так ты явно задаешь, в каком размере будет открыт сайт.

screenshot: 'only-on-failure' — скриншот будет делаться только при падении теста. Это полезно для отладки.

Теперь посмотрим, как работает baseURL:

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

test('открытие главной страницы', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveURL('http://localhost:3000/');
});

Если в конфигурации задан baseURL: 'http://localhost:3000', то вызов page.goto('/') откроет именно этот адрес с путем /. Документация прямо указывает, что baseURL используется в действиях вроде page.goto('/'). (playwright.dev)

Это делает тесты короче и удобнее. Вместо длинных строк в каждом файле у нас есть одна централизованная настройка.

Параллельный запуск, повторы и поведение на CI

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

В официальных примерах Playwright часто показываются такие настройки: fullyParallel, forbidOnly, retries, workers, причем для CI они нередко зависят от process.env.CI. (playwright.dev)

Вот понятный пример:

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

export default defineConfig({
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
});

Разберем смысл.

fullyParallel: true — разрешает более активный параллельный запуск тестов. Это ускоряет выполнение, если тесты не мешают друг другу.

forbidOnly: !!process.env.CI — не дает случайно закоммитить test.only в CI. Если разработчик оставил test.only, сборка упадет, и это полезная защита.

retries — сколько раз повторять упавший тест. В локальной разработке часто ставят 0, а на CI — 2.

workers — количество параллельных воркеров. На CI иногда уменьшают их число, чтобы запуск был стабильнее.

Что такое process.env.CI? Это чтение переменной окружения. Если проект запущен в CI-среде, значение обычно существует, и тогда можно автоматически включать более строгие или более осторожные настройки.

Это хороший пример того, как конфигурация помогает разделять локальную работу и запуск в пайплайне. У разработчика могут быть удобные настройки для ежедневной работы, а на CI — более контролируемые правила.

Репортеры: как смотреть результаты запуска

После запуска тестов нужен понятный результат. Где упало? Что прошло? Есть ли красивый отчет, который можно открыть в браузере? За это отвечает reporter.

В документации Playwright сказано, что можно использовать встроенные репортеры и настраивать их через конфигурацию. Также можно использовать разные репортеры для локального режима и для CI. (playwright.dev)

Простой пример:

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

export default defineConfig({
  reporter: 'html',
});

html создает HTML-отчет, который удобно открывать и изучать после запуска.

Другой пример:

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

export default defineConfig({
  reporter: process.env.CI ? 'dot' : 'list',
});

Здесь используется условие:

  • в CI отчет будет более компактным — dot;
  • локально — более подробным — list.

Это полезно, потому что потребности отличаются. Локально разработчику обычно хочется видеть больше деталей прямо в терминале. На CI часто нужен краткий вывод и отдельные артефакты.

projects: запуск в разных браузерах и конфигурациях

Одна из сильных сторон Playwright Test — проекты. Документация определяет project как логическую группу тестов с общей конфигурацией и объясняет, что проекты позволяют запускать тесты в разных браузерах, на разных устройствах и вообще в разных вариантах окружения. (playwright.dev)

Пример:

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

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Что здесь происходит?

projects — это массив настроек. Каждый объект внутри массива описывает отдельный проект.

name — имя проекта. Оно будет видно в результатах запуска.

use — настройки именно для этого проекта. Здесь мы берем готовые параметры устройств и браузеров из devices.

Оператор ... — это spread syntax. Он раскладывает свойства объекта внутрь другого объекта. В данном случае мы берем готовую конфигурацию устройства и вставляем ее в use.

Практический смысл очень большой. Один и тот же тест можно прогонять сразу в нескольких браузерах, не копируя код. Это уже не просто удобство, а основа кроссбраузерной проверки.

Проекты можно использовать не только для браузеров. Например, один проект может ходить на staging, другой — на production-like среду. Или один проект может запускаться в авторизованном состоянии, а другой — без логина. Документация прямо указывает, что projects подходят и для разных окружений, и для разных наборов retries/timeouts, и для разделения тестов по логике. (playwright.dev)

webServer: как автоматически поднять приложение перед тестами

Очень частая ситуация у новичка: написал тест, запускает его, а сайт еще не поднят. В итоге тест падает не потому, что логика неверная, а потому что приложение просто недоступно.

Для этого в Playwright есть webServer. Документация описывает его как способ автоматически запускать локальный dev server перед стартом тестов. (playwright.dev)

Пример:

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

export default defineConfig({
  webServer: {
    command: 'npm run start',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});

Разберем смысл.

command — команда, которой нужно поднять приложение.

url — адрес, по которому Playwright проверяет, что сервер уже доступен.

reuseExistingServer — можно ли использовать уже работающий сервер. Локально это удобно: если приложение уже запущено, Playwright не будет поднимать его заново.

Это делает запуск тестов гораздо стабильнее и удобнее. Особенно в учебных и небольших проектах, где тесты зависят от локального приложения.

Полезный пример полной базовой конфигурации

Теперь соберем все вместе в один понятный учебный пример:

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

export default defineConfig({
  testDir: './tests',
  timeout: 30_000,
  expect: {
    timeout: 5_000,
  },

  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',

  use: {
    baseURL: 'http://localhost:3000',
    headless: true,
    screenshot: 'only-on-failure',
    trace: 'on-first-retry',
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],

  webServer: {
    command: 'npm run start',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});

Что дает такая конфигурация:

  • Playwright ищет тесты в папке tests;
  • каждому тесту дается до 30 секунд;
  • ожидания expect ждут до 5 секунд;
  • тесты могут идти параллельно;
  • на CI запрещен test.only;
  • на CI упавшие тесты повторяются;
  • после запуска формируется HTML-отчет;
  • тесты используют общий baseURL;
  • при падении сохраняются полезные артефакты;
  • перед стартом поднимается локальное приложение;
  • тесты запускаются в Chromium.

Это уже очень хорошая стартовая конфигурация для реального проекта. Она не перегружена, но покрывает основные потребности.

Где конфигурация особенно полезна на практике

Пока тема может казаться чисто технической, но на практике конфигурация решает очень прикладные задачи.

Во-первых, она убирает дублирование. Если не использовать конфиг, одинаковые URL, настройки браузера и параметры запуска начнут размазываться по разным файлам.

Во-вторых, она делает проект единообразным. Каждый новый тест запускается в тех же условиях, что и остальные.

В-третьих, она помогает разделять локальную работу и CI. Локально тебе нужен удобный режим разработки, а на CI — стабильность, повторы и защита от случайностей.

В-четвертых, она открывает путь к масштабированию проекта. Сначала у тебя один браузер и один URL. Потом появляются Firefox, WebKit, staging, mobile-профили, отдельные отчеты. Без конфигурации это быстро стало бы хаосом. С конфигурацией — это естественное развитие проекта. Возможность глобально задавать use, переопределять настройки на уровне проекта и при необходимости менять их для отдельных тестов прямо предусмотрена официальной документацией. (playwright.dev)

Итоговое понимание

Главная идея конфигурации Playwright Test в том, что она выносит общие правила запуска тестов в одно центральное место. Тесты при этом остаются сосредоточены на поведении приложения, а не на повторяющихся технических деталях.

Когда ты работаешь с playwright.config.ts, ты по сути описываешь среду, в которой живут все твои тесты: где их искать, как долго ждать, в каком браузере запускать, по какому адресу открывать сайт, как собирать результаты и как готовить приложение к запуску. Именно поэтому конфигурация — не второстепенная часть проекта, а его фундамент.

Если понять эту логику, дальше будет намного легче осваивать более точечные настройки Playwright. Ты уже не будешь воспринимать конфиг как набор непонятных опций. Вместо этого ты увидишь в нем карту всего тестового окружения: что запускается, в каких условиях и по каким правилам.