Урок по треку Автоматизация тестирования 8 мин

Playwright за 8 минут

Автоожидание, локаторы, web-first assertions, контексты, фикстуры, трейсы.

Playwright это фреймворк Microsoft для браузерной автоматизации: Chromium, Firefox и WebKit одним API. Есть версии для TypeScript/JavaScript, Python, Java и .NET, но полный тестовый раннер @playwright/test (фикстуры, параллельность, отчёты, трейсы) есть именно в Node. В Python обычно берут pytest с плагином pytest-playwright.

Минимальный тест

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

test('поиск товара', async ({ page }) => {
  await page.goto('/');
  await page.getByRole('searchbox', { name: 'Поиск' }).fill('чайник');
  await page.getByRole('button', { name: 'Найти' }).click();
  await expect(page.getByTestId('product-card')).toHaveCount(12);
});

page это фикстура: раннер сам создаёт браузер, изолированный контекст и вкладку, а после теста всё закрывает.

Браузер, контекст, страница

  • Browser: запущенный процесс браузера, дорогой ресурс, переиспользуется воркером.
  • BrowserContext: изолированная сессия, как профиль в режиме инкогнито: свои куки, localStorage, кеш. Создаётся за миллисекунды. Каждый тест получает новый контекст, поэтому тесты не делят состояние.
  • Page: вкладка внутри контекста.

Автоожидание и web-first assertions

Перед действием Playwright ждёт, что элемент видим, стабилен, получает события и включён. Проверки expect(locator) повторяются до таймаута:

await expect(page.getByText('Заказ оформлен')).toBeVisible();   // ждёт до 5 с по умолчанию
expect(await page.getByText('Заказ оформлен').isVisible()).toBe(true); // снимок, без ожидания

Вторая строка частая ошибка: isVisible() возвращает состояние в момент вызова, и тест флакает. Таймауты по умолчанию: 30 секунд на тест, 5 секунд на expect.

Ещё полезно: expect.soft (проверка не прерывает тест), expect.poll (опрос произвольной функции, например API), expect(page).toHaveScreenshot() (скриншотное сравнение).

Фикстуры

Свои фикстуры объявляются через test.extend:

export const test = base.extend<{ cartPage: CartPage }>({
  cartPage: async ({ page }, use) => {
    const cart = new CartPage(page);
    await cart.open();
    await use(cart);       // здесь выполняется тест
    await cart.clear();    // teardown
  },
});

Фикстура создаётся только если тест её запросил. Бывают фикстуры уровня теста и уровня воркера ({ scope: 'worker' }).

Авторизация один раз

Логин через UI в каждом тесте дорог. Типовой рецепт: setup-проект логинится и сохраняет storageState (куки и localStorage) в файл, остальные проекты зависят от него (dependencies) и стартуют уже авторизованными.

Сеть

  • page.route('**/api/products', route => route.fulfill({ json: [...] })) подменяет ответ.
  • Фикстура request делает API-запросы без браузера: удобно готовить данные.
  • page.waitForResponse(...) ждёт конкретный ответ.

Параллельность и конфиг

playwright.config.ts: projects (браузеры, устройства), workers, fullyParallel, retries, use: { baseURL, trace, screenshot, video }. По умолчанию файлы распределяются по воркерам, тесты внутри файла идут последовательно; fullyParallel: true распараллеливает и их. Для CI есть --shard=1/4.

Отладка

  • npx playwright codegen записывает действия в код.
  • --ui режим и --debug с инспектором.
  • Трейс (trace: 'on-first-retry'): шаги, снимки DOM, сеть, консоль. Открывается npx playwright show-trace.

Частые ошибки

  • page.waitForTimeout(3000) вместо ожидания состояния.
  • isVisible(), textContent() и count() в expect(...) вместо web-first assertions.
  • Логин через UI в каждом тесте.
  • Общие данные между тестами при fullyParallel.

Что спросят на собесе

  • Чем Playwright отличается от Selenium?
  • Что такое BrowserContext и зачем он нужен?
  • Как работает автоожидание и чем toBeVisible лучше isVisible?
  • Как сделать авторизацию один раз на весь прогон?
  • Как мокать сеть и как отлаживать упавший в CI тест?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.