Retour à l'accueil

Stabilisation des Tests Playwright en CI

L'article décrit la méthodologie pour stabiliser les tests Playwright en CI en utilisant les Dependency Projects, les assertions web-first et la sélection appropriée des locateurs. Des exemples de configuration et de code pour les projets d'entreprise sont fournis.

Playwright : Éliminer les Flakes en CI avec les Dependency Projects
Advertisement 728x90

Stabiliser les tests Playwright dans CI : projets de dépendance et assertions web-first

Les dépendances en chaîne dans Playwright empêchent l'exécution des tests dans des environnements instables, préservant ainsi les ressources CI et réduisant les faux positifs.

Tout d'abord, l'authentification via API est effectuée avec persistance de l'état de stockage. Ensuite, un contrôle de santé vérifie la disponibilité de l'API. Seulement après cela, les tests principaux UI s'exécutent.

Avantages par rapport à globalSetup :

Google AdInline article slot
  • Traces complètes incluant requêtes réseau, captures d'écran et journaux de console.
  • Comportement "fail-fast" : si la configuration échoue, les projets dépendants sont immédiatement interrompus.
  • Isolation : chaque étape peut être testée individuellement avec npx playwright test --project=auth-setup.

Configuration dans playwright.config.ts :

export default defineConfig({
  projects: [
    {
      name: 'auth-setup',
      testMatch: /.*\.auth\.setup\.ts/,
    },
    {
      name: 'healthcheck',
      testMatch: /.*\.health\.setup\.ts/,
      dependencies: ['auth-setup'],
    },
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
      dependencies: ['healthcheck'],
    },
  ],
});

L'authentification basée sur l'API réduit considérablement le temps de configuration : une requête POST prend 50 à 100 ms contre 2 à 5 secondes pour une connexion UI.

Exemple de test auth-setup :

Google AdInline article slot
test('setup', async ({ request }) => {
  await request.post('/api/login', { data: { user, pass } });
  await request.storageState({ path: '.auth/user.json' });
});

Les graphes de dépendance éliminent les conditions de course lors des exécutions parallèles de tests.

Choisir ses locateurs avec sagesse

Le choix des locateurs influence directement la robustesse des tests face aux modifications de l’interface. Séparez-les selon leur usage : utilisez getByTestId pour les actions, et getByRole ou getByLabel pour les assertions.

Meilleures pratiques :

Google AdInline article slot
  • Actions (clic, saisie) : page.getByTestId('add-to-cart-button').click() — indépendant du texte ou du style.
  • Vérification de texte/état : expect(page.getByRole('heading')).toHaveText('Mon compte').
  • Champs de saisie : page.getByLabel('Email').fill('[email protected]').
  • Compteurs : expect(locator).toHaveText('3').

Les sélecteurs CSS ne doivent être utilisés qu’en dernier recours. Former votre équipe à une utilisation correcte des locateurs rapporte dix fois plus à grande échelle.

Assertions web-first vs instabilité

Les vérifications par instantané comme await loc.isVisible() sont sujettes aux conditions de course. Les assertions web-first avec pollings garantissent une stabilité optimale.

Comparaison des assertions :

| Vérification | Instantané (sans attente) | Web-first (polling) |

|---------------|----------------------------|----------------------|

| Visibilité | await loc.isVisible() | expect(loc).toBeVisible() |

| Texte | await loc.textContent() | expect(loc).toHaveText('Texte') |

| Nombre | await loc.count() | expect(loc).toHaveCount(3) |

| Attribut | await loc.getAttribute('href') | expect(loc).toHaveAttribute('href', '/chemin') |

| Case à cocher | await loc.isChecked() | expect(loc).toBeChecked() |

| État | await loc.isEnabled() | expect(loc).toBeEnabled() |

Le polling réessaie toutes les 100 ms jusqu’à expiration du délai, ignorant les clignotements temporaires de l’UI.

Hydratation et force : true

Le désaccord d’hydratation survient dans les applications SSR/SSG lorsque le balisage côté serveur existe mais que les gestionnaires JS ne sont pas encore attachés.

Attendez les marqueurs d’hydratation :

  • await page.waitForSelector('.hydrated', { state: 'attached' })
  • await expect(page.locator('#global-loader')).toBeHidden()

force: true désactive les vérifications d'actionnalité (visible, stable, activé, réception d’événements), transformant le test en script DOM brut. À utiliser avec parcimonie et toujours avec un commentaire — idéal pour les cas limites comme les champs de fichier.

Points clés

  • Projets de dépendance construisent un graphe de dépendance, empêchant les tests de s’exécuter dans des environnements non prêts.
  • Assertions web-first avec polling éliminent 80 % des instabilités causées par les conditions de course.
  • Séparation des locateurs par rôle renforce la résilience aux refacturations UI.
  • Authentification API accélère la configuration de 20 à 50 fois par rapport à la connexion UI.
  • Traces au lieu de captures fournissent un contexte complet des échecs en CI.

— Editorial Team

Advertisement 728x90

Lire ensuite