Bonnes pratiques Playwright

Ce chapitre résume les bonnes pratiques les plus importantes pour écrire et maintenir des tests Playwright, vous aidant à écrire des tests stables et maintenables.


Philosophie des tests

Tester le comportement visible par l'utilisateur

Les tests automatisés doivent vérifier ce que les utilisateurs finaux peuvent voir et avec quoi ils peuvent interagir, plutôt que de vérifier les détails d'implémentation du code.

Par exemple, les tests doivent vérifier que le texte correct est affiché sur la page, que les boutons sont cliquables et que la soumission du formulaire navigue vers la bonne page, plutôt que de vérifier la valeur de retour d'une fonction JavaScript ou la structure interne du DOM.

Exemple

// Non recommandé : tester les détails d'implémentation
expect(await page.evaluate(() => window.__store.getState().user.name))
  .toBe('example');

// Recommandé : tester ce que les utilisateurs voient
await expect(page.getByText('Welcome, example')).toBeVisible();

Isolation des tests

Chaque test doit êtrecomplètement indépendantdes autres tests, et ne pas dépendre de l'état d'un test précédent.

Playwright fournit un contexte indépendant par défaut, mais vous devez également vous assurer que vous ne dépendez pas de l'ordre d'exécution des tests.

Exemple

// Non recommandé : les tests dépendent les uns des autres
let createdId;
test('Create resource', async ({ request }) => {
  const resp = await request.post('/api/items');
  createdId = (await resp.json()).id;  // État partagé
});
test('Use created resource', async ({ page }) => {
  await page.goto(`/items/${createdId}`);  // Dépend du résultat du test précédent
});

// Recommandé : chaque test est autonome
test('Créer et utiliser une ressource', async ({ request, page }) => {
  const resp = await request.post('/api/items');
  const id = (await resp.json()).id;
  await page.goto(`/items/${id}`);
  await expect(page.getByText('Détails de la ressource')).toBeVisible();
});

Principes de priorité des localisateurs

Utiliser les localisateurs dans l'ordre recommandé peut améliorer la stabilité des tests.

PrioritéMéthodeScénario d'application
1getByRole()L'élément a un rôle ARIA clair
2getByLabel()Élément de formulaire associé à une étiquette
3getByPlaceholder()Le champ de saisie a un texte indicatif
4getByText()L'élément a un texte explicite
5getByAltText()L'image a un attribut alt
6getByTitle()L'élément a un attribut title
7getByTestId()Repli
8locator()CSS/XPath, en dernier recours

Essayez d'éviter d'utiliser les noms de classes CSS comme localisateurs.

Les noms de classes sont susceptibles de changer en raison de la refactorisation des styles, ce qui entraîne des échecs de tests à grande échelle.


Évitez les attentes inutiles

Tirez parti du mécanisme d'attente automatique de Playwright, évitez le codage manuelsleepouwaitForTimeout。

Exemple

// Non recommandé : attentes codées en dur
await page.waitForTimeout(3000);
await page.getByText('Chargement des données terminé').click();

// Recommandé : s'appuyer sur l'attente automatique et les assertions
await expect(page.getByText('Chargement des données...')).toBeHidden({ timeout: 10000 });
await page.getByText('Chargement des données terminé').click();

Ne testez pas les services tiers

Ne testez que ce que vous pouvez contrôler ; ne dépendez pas de la disponibilité des services tiers.

Exemple

// Non recommandé : dépendre d'un CDN ou d'une API externe
await page.goto('https://www.example.com/');
// La page peut charger Google Analytics, des polices externes, etc.

// Recommandé : intercepter les requêtes tierces, simuler les services externes
await page.route('**/*analytics*', route => route.abort());
await page.route('**/external-api/**', route => {
  route.fulfill({ json: { status: 'ok' } });
});

Utilisez expect.soft() pour des assertions souples

Lorsque vous vérifiez plusieurs conditions indépendantes, les assertions souples peuvent signaler tous les échecs d'un coup au lieu de s'arrêter au premier échec.

Exemple

// Recommandé : les assertions souples vérifient tous les champs en une seule fois
await expect.soft(page.getByLabel('Username')).toBeVisible();
await expect.soft(page.getByLabel('Password')).toBeVisible();
await expect.soft(page.getByLabel('Email')).toBeVisible();
await expect.soft(page.getByRole('button', { name: 'Register' })).toBeEnabled();
// Si plusieurs champs sont manquants, signalez-les tous en même temps

Organiser les fichiers de test de manière raisonnable

PratiqueDescription
Diviser les fichiers par module fonctionnellogin.spec.ts、checkout.spec.tswait
Utiliser describe pour regrouperMettre les tests associés danstest.describe()Moyenne
Bien utiliser beforeEachExtraire les étapes de navigation et de configuration répétées dansbeforeEach
Noms de tests descriptifsDe bons noms expliquent « ce qui a été fait » et « ce qui est attendu »
Extraire le code communLes helpers utilisés dans plus de 3 fichiers doivent être extraits dans un module partagé
Ne pas abuser du DRY2-3 lignes de répétition sont plus faciles à maintenir qu'une sur-abstraction

Dépannage courant

Tests instables

Causes et solutions des tests instables :

CauseSolution
Le délai d'attente codé en dur n'est pas assez longUtiliser un mécanisme d'attente automatique au lieu d'attentes fixes
Dépendre de services tiersUtiliserroute()Simuler les requêtes externes
Les animations provoquent des changements de position des élémentsDans la configurationanimations: 'disabled'
Résidus de données entre les testsS'assurer que chaque test crée et nettoie les données de manière indépendante
Logique liée au tempsUtiliserpage.clockHeure fixe

Le localisateur ne trouve pas l'élément

Étapes de dépannage :

  • Vérifier si l'élément est dans le DOM (utiliseztoBeAttached()plutôt quetoBeVisible())
  • Vérifier si l'élément est dans la fenêtre d'affichage
  • Vérifier s'il est imbriqué dans une iframe
  • Utilisez Pick Locator en mode UI pour vérifier le localisateur
  • Vérifier s'il y a plusieurs éléments correspondants (Locator requiert le mode strict par défaut)
Autres extensions