Lancer les mêmes tests Playwright contre les environnements local, staging et production exige de lire l'URL de base et les identifiants depuis des variables d'environnement. Les coder en dur dans la config oblige à modifier des fichiers manuellement entre chaque environnement. Changer d'environnement ne nécessite aucune modification de fichier.

Le problème des URLs codées en dur

// Mauvais — pas de flexibilité
use: {
  baseURL: 'https://staging.myapp.com',
},

Pour travailler en local, vous modifiez l'URL manuellement. Quand la CI doit cibler un déploiement de branche, quelqu'un se souvient de la remettre. Quelqu'un l'oublie. Les tests s'exécutent contre le mauvais environnement. L'erreur est trompeuse parce que tout passe, mais contre des données périmées.

Variables d'environnement : la bonne approche

Lisez l'URL de base depuis une variable d'environnement :

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

export default defineConfig({
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
  },
});

Lancer les tests :

# Local
npx playwright test

# Staging
BASE_URL=https://staging.myapp.com npx playwright test

# Production (smoke tests uniquement)
BASE_URL=https://myapp.com npx playwright test --grep @smoke

Aucun changement de code entre les environnements. Juste une variable d'environnement différente.

Utiliser dotenv en développement local

Répéter BASE_URL=... à chaque fois devient vite pénible. Utilisez un fichier .env :

# .env.local
BASE_URL=http://localhost:3000
API_TOKEN=dev-token-abc123
TEST_USER_EMAIL=test@example.com
TEST_USER_PASSWORD=testpass123

Chargez-le dans votre config :

npm install -D dotenv

// playwright.config.ts
import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';
import path from 'path';

dotenv.config({ path: path.resolve(__dirname, '.env.local') });
dotenv.config({ path: path.resolve(__dirname, '.env') });

export default defineConfig({
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
  },
});

Ajoutez .env.local au .gitignore. Committez .env avec des valeurs par défaut sûres (sans secrets). Les membres de l'équipe créent leur propre .env.local pour leurs identifiants locaux.

Configs multi-environnements

Pour les projets avec des paramètres très différents selon l'environnement, utilisez des fichiers de config séparés :

playwright.config.ts           # Config de base, paramètres partagés
playwright.config.staging.ts   # Surcharges staging
playwright.config.prod.ts      # Surcharges production (smoke uniquement)

// playwright.config.staging.ts
import { defineConfig } from '@playwright/test';
import baseConfig from './playwright.config';

export default defineConfig({
  ...baseConfig,
  use: {
    ...baseConfig.use,
    baseURL: 'https://staging.myapp.com',
    video: 'on-first-retry',
  },
  retries: 2,
});

Lancez avec :

npx playwright test --config=playwright.config.staging.ts

Ce schéma fonctionne bien pour les pipelines CI où différentes étapes nécessitent des nombres de tentatives, des configurations vidéo ou des reporters différents.

Accéder aux variables d'environnement dans les tests

Ne faites pas passer les variables d'environnement directement dans les fichiers de test. Ça couple la logique de test à l'infrastructure. Utilisez des fixtures à la place :

// fixtures/env.ts
import { test as base } from '@playwright/test';

type EnvFixtures = {
  testUser: { email: string; password: string };
  apiToken: string;
};

export const test = base.extend<EnvFixtures>({
  testUser: async ({}, use) => {
    const email = process.env.TEST_USER_EMAIL;
    const password = process.env.TEST_USER_PASSWORD;

    if (!email || !password) {
      throw new Error('TEST_USER_EMAIL and TEST_USER_PASSWORD must be set');
    }

    await use({ email, password });
  },

  apiToken: async ({}, use) => {
    const token = process.env.API_TOKEN;
    if (!token) throw new Error('API_TOKEN must be set');
    await use(token);
  },
});

Les tests utilisent la fixture, pas process.env directement :

import { test } from '../fixtures/env';
import { expect } from '@playwright/test';

test('l\'utilisateur peut se connecter', async ({ page, testUser }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill(testUser.email);
  await page.getByLabel('Mot de passe').fill(testUser.password);
  await page.getByRole('button', { name: 'Se connecter' }).click();
  await expect(page).toHaveURL('/dashboard');
});

L'avantage : si la variable d'environnement est absente, vous obtenez une erreur claire au niveau de la fixture plutôt qu'un échec confus en plein milieu du test.

Variables d'environnement en CI/CD

Dans GitHub Actions, définissez les secrets dans les paramètres du dépôt, puis transmettez-les aux tests :

# .github/workflows/tests.yml
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      BASE_URL: ${{ vars.STAGING_URL }}
      API_TOKEN: ${{ secrets.API_TOKEN }}
      TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
      TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test

Utilisez vars (pas secrets) pour les valeurs non sensibles comme l'URL de staging : elles sont visibles dans les logs CI, ce qui aide au débogage. Utilisez secrets pour les identifiants, tokens et mots de passe.

Données de test spécifiques à l'environnement

Certains tests ne doivent s'exécuter que dans certains environnements. Utilisez des tags et des vérifications d'environnement :

test('smoke test du flux de paiement', {
  tag: '@smoke',
  annotation: { type: 'env', description: 'staging and production only' },
}, async ({ page }) => {
  test.skip(
    process.env.BASE_URL?.includes('localhost') === true,
    'Les tests de paiement nécessitent un environnement staging ou production'
  );

  // corps du test...
});

Ou utilisez une fixture qui résout l'environnement courant :

const currentEnv = process.env.BASE_URL?.includes('staging')
  ? 'staging'
  : process.env.BASE_URL?.includes('localhost')
  ? 'local'
  : 'production';

Cela évite les vérifications if (process.env.BASE_URL === '...') dispersées dans les fichiers de test.

Ce qui va dans les variables d'environnement vs le fichier de config

| Configuration | Où ça va |

|---|---|

| URL de base | Variable d'environnement |

| Tokens API, mots de passe | Variable d'environnement (secret) |

| Type de navigateur | Fichier de config |

| Nombre de tentatives | Fichier de config (par environnement si nécessaire) |

| Valeurs de timeout | Fichier de config |

| Seeds de données de test | Fixtures |

| Feature flags pour le comportement des tests | Variable d'environnement |

La règle : tout ce qui diffère entre environnements est une variable d'environnement. Tout ce qui est un paramètre stable du framework de test va dans le fichier de config.

→ See also: Fichier de Configuration Playwright Expliqué: Toutes les Options à Connaître | Variables d'Environnement dans les Tests Playwright: Un Guide Complet | GitHub Actions pour Tests Playwright: La Configuration Complète (2026)