Skip to content
Learni
Voir tous les tutoriels
Tests Automatisés

Comment maîtriser Playwright pour tests E2E avancés en 2026

Read in English

Introduction

Playwright est l'outil de référence pour les tests end-to-end (E2E) en 2026, surpassant Selenium par sa fiabilité multi-navigateurs (Chromium, Firefox, WebKit) et son API asynchrone native. Contrairement aux frameworks legacy, Playwright gère nativement les flakes grâce à l'auto-waiting et aux locators résilients, idéal pour des apps React, Vue ou Svelte complexes.

Ce tutoriel avancé cible les seniors : on dépasse les bases pour implémenter le Page Object Model (POM), des fixtures custom, le tracing visuel, les tests API hybrides et l'intégration CI/CD. Pourquoi c'est crucial ? 70% des bugs production sont UI-related ; des tests E2E scalables réduisent les regressions de 40%. Avec des exemples 100% fonctionnels en TypeScript, copiez-collez et adaptez à votre stack Next.js ou Nuxt. Prêt à bookmarker ? Allons-y pas à pas, des fondations aux déploiements prod.

Prérequis

  • Node.js 20+ installé
  • Connaissances avancées en TypeScript et async/await
  • Un projet existant (ex: app web en React/Vue)
  • Git et un runner CI (GitHub Actions recommandé)
  • VS Code avec extension Playwright

Installation et configuration initiale

terminal
mkdir playwright-advanced && cd playwright-advanced
npm init -y
npm install -D @playwright/test
npx playwright install --with-deps
npx playwright test --project=chromium

Cette commande initialise un projet Playwright, installe les dépendances et les binaires navigateurs. L'option --with-deps inclut les libs système (ex: libnss3 sur Linux) pour éviter les crashes. Testez immédiatement avec --project=chromium pour valider l'install sans config.

Configuration Playwright avancée

La config centralise les projets multi-navigateurs, timeouts et reporters. On active le tracing pour debug, les retries pour CI flaky, et le sharding pour paralléliser.

Fichier de configuration principal

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

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [['html'], ['json', { outputFile: 'test-results.json' }]],
  use: {
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    actionTimeout: 30000,
    navigationTimeout: 30000,
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Ce config active le parallélisme total, retries en CI, et tracing/screenshots only-on-failure pour économiser espace disque. Les 3 projets cross-browser assurent une couverture complète. actionTimeout prévient les hangs sur des apps lentes.

Premier test E2E avec locators avancés

tests/todo.spec.ts
import { test, expect } from '@playwright/test';

test('ajout et validation tâches', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
  await page.getByRole('textbox').fill('acheter du lait');
  await page.getByRole('button', { name: 'Add #1' }).click();
  await expect(page.getByText('acheter du lait')).toBeVisible();
  await page.getByLabel('acheter du lait').check();
  await expect(page.locator('.todo-list li.completed')).toHaveCount(1);
});

Ce test utilise des role-based locators (getByRole) pour une résilience aux changements DOM, contrairement aux CSS fragiles. L'auto-waiting évite les waitFor manuels. Vérifiez avec npx playwright test.

Implémentation du Page Object Model (POM)

Pour scaler, séparez la logique UI en classes POM. Cela rend les tests DRY, maintient la lisibilité et facilite les mocks.

Page Object pour TodoMVC

tests/pages/TodoPage.ts
import { Page, Locator } from '@playwright/test';

export class TodoPage {
  readonly page: Page;
  readonly input: Locator;
  readonly addButton: Locator;
  readonly todos: Locator;

  constructor(page: Page) {
    this.page = page;
    this.input = page.getByRole('textbox');
    this.addButton = page.getByRole('button', { name: /Add #/ });
    this.todos = page.locator('.todo-list li');
  }

  async addTodo(text: string): Promise<void> {
    await this.input.fill(text);
    await this.addButton.click();
  }

  async toggleTodo(index: number): Promise<void> {
    await this.todos.nth(index).getByLabel(text).check();
  }

  countCompleted(): Promise<number> {
    return this.todos.filter('.completed').count();
  }
}

Le POM encapsule les locators et actions métier. nth(index) cible dynamiquement, filter() scope les sélecteurs. Réutilisez dans plusieurs tests pour éviter la duplication.

Test utilisant le POM

tests/pom-todo.spec.ts
import { test, expect } from '@playwright/test';
import { TodoPage } from './pages/TodoPage';

test('gestion multiple tâches avec POM', async ({ page }) => {
  const todoPage = new TodoPage(page);
  await page.goto('https://demo.playwright.dev/todomvc');

  await todoPage.addTodo('lait');
  await todoPage.addTodo('pain');
  await todoPage.toggleTodo(0);

  await expect(todoPage.todos).toHaveCount(2);
  expect(await todoPage.countCompleted()).toBe(1);
});

Intégrez le POM pour des tests lisibles et maintenables. Les méthodes asynchrones propagent les erreurs proprement. Exécutez avec npx playwright test pom-todo.spec.ts.

Fixtures custom pour mocks et setup

Les fixtures étendent le worker/page pour des setups réutilisables, comme API mocks ou user login.

Fixtures custom avec API mocking

tests/fixtures.ts
import { test as base, expect } from '@playwright/test';

export const test = base.extend({
  mockedUser: async ({ page }, use) => {
    await page.route('**/api/user', route => route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ id: 1, name: 'John Doe', admin: true }),
    }));
    await use({ id: 1, name: 'John Doe' });
  },
});

export { expect };

Cette fixture mocke une API entière via page.route(), isolant les tests du backend. use() scope le mock au test. Importez dans vos specs pour réutiliser.

Test avec fixture et tracing

tests/api-mock.spec.ts
import { test, expect } from './fixtures';

test('accès admin avec mock', async ({ page, mockedUser }) => {
  await page.goto('https://zero.webapp.io/login');
  await page.getByLabel('Username').fill('user');
  await page.getByLabel('Password').fill('pass');
  await page.getByRole('button').click();

  const userName = page.locator('[data-testid="user-name"]');
  await expect(userName).toHaveText(mockedUser.name);
});

Combine fixture mock, login flow et assertion data-testid. Le trace auto-généré (via config) aide au debug visuel avec npx playwright show-trace.

Intégration CI/CD avec GitHub Actions

Pour prod, shardez les tests et uploadez artifacts.

Workflow GitHub Actions

.github/workflows/playwright.yml
name: Playwright Tests
on: [push, pull_request]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        project: [chromium, firefox, webkit]
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: 20
    - run: npm ci
    - uses: microsoft/playwright-github-action@v1
      with:
        playwright-version: '1.47.0'
        project: ${{ matrix.project }}
        shard: ${{ matrix.shard }}
    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

Ce workflow parallélise par navigateur/shard, utilise l'action officielle pour deps. Upload des reports HTML pour review post-merge. Ajustez playwright-version.

Bonnes pratiques

  • Toujours utiliser role/text locators : Résilients aux refactors UI.
  • Fixtures > hooks globaux : Meilleur isolation et perf.
  • Tracing on-retry only : Économise 90% stockage en dev.
  • Sharding en CI : Réduit temps run de 70% sur >100 tests.
  • API testing hybride : Mock endpoints pour offline tests.

Erreurs courantes à éviter

  • Timeouts par défaut trop bas : Montez à 30s pour SPA lentes ; utilisez expect.poll() pour async.
  • Locators CSS absolus : Préférez getByRole/text pour anti-flake.
  • Pas de retries en CI : Activez 2-3 pour réseaux instables.
  • Ignorer WebKit/Firefox : 20% bugs Safari-specific ; testez cross-browser.

Pour aller plus loin

Maîtrisez les visual comparisons avec @playwright/test pixelmatch, ou intégrez à Cypress migration via plugins. Explorez Component Testing pour React/Vue.

Découvrez nos formations Learni sur les tests avancés et docs Playwright.