La configuration Playwright se divise en deux parties. Les paramètres du framework (navigateur, timeouts, reporters) appartiennent à playwright.config.ts. Les valeurs spécifiques à l'environnement (URLs, identifiants, clés API) appartiennent aux variables d'environnement. Mélanger les deux est l'une des sources de friction les plus courantes dans les projets Playwright.

Ce qui va où

Dans playwright.config.ts (commité dans le dépôt) :

export default defineConfig({
  timeout: 30000,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 4 : undefined,
  reporter: [['html'], ['list']],
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
});

Dans les fichiers .env ou les secrets CI (jamais commité pour les secrets) :

BASE_URL=https://staging.myapp.com
API_KEY=sk-test-abc123
TEST_USER_EMAIL=testuser@example.com
TEST_USER_PASSWORD=SecurePass123!
DATABASE_URL=postgresql://localhost:5432/testdb

Configurer dotenv

npm install -D dotenv

Créez .env avec des valeurs par défaut sûres (sans vrais identifiants) :

# .env
BASE_URL=http://localhost:3000
TEST_USER_EMAIL=test@example.com
TEST_USER_PASSWORD=
DATABASE_URL=

Créez .env.local avec de vraies valeurs locales (ajouté au gitignore) :

# .env.local — jamais commité
TEST_USER_EMAIL=realtest@example.com
TEST_USER_PASSWORD=RealPassword123
DATABASE_URL=postgresql://localhost:5432/myapp_test

Chargez dans la config :

// playwright.config.ts
import dotenv from 'dotenv';
import path from 'path';

// Charger .env.local en premier (surcharge .env)
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 au .gitignore :

.env.local
playwright/.auth/
test-results/
playwright-report/

Variables d'environnement typées

process.env.VARIABLE retourne string | undefined. Détecter les variables manquantes au moment d'un test est mauvais. Détectez-les au démarrage :

// utils/env.ts
function requireEnv(name: string): string {
  const value = process.env[name];
  if (!value) {
    throw new Error(`La variable d'environnement ${name} est requise mais non définie`);
  }
  return value;
}

export const env = {
  baseURL: process.env.BASE_URL || 'http://localhost:3000',
  apiKey: requireEnv('API_KEY'),
  testUser: {
    email: requireEnv('TEST_USER_EMAIL'),
    password: requireEnv('TEST_USER_PASSWORD'),
  },
};

Import dans les tests :

import { env } from '../utils/env';

test('connexion avec les identifiants de test', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill(env.testUser.email);
  await page.getByLabel('Mot de passe').fill(env.testUser.password);
});

Si TEST_USER_EMAIL n'est pas défini, vous obtenez une erreur claire au démarrage : La variable d'environnement TEST_USER_EMAIL est requise mais non définie. Pas un échec cryptique en plein milieu d'un test.

Configuration par projet

Pour plusieurs environnements de test, utilisez des projets Playwright avec des paramètres différents :

// playwright.config.ts
const environments = {
  local: {
    baseURL: 'http://localhost:3000',
    apiURL: 'http://localhost:8000',
  },
  staging: {
    baseURL: 'https://staging.myapp.com',
    apiURL: 'https://api-staging.myapp.com',
  },
  production: {
    baseURL: 'https://myapp.com',
    apiURL: 'https://api.myapp.com',
  },
};

const currentEnv = (process.env.TEST_ENV as keyof typeof environments) || 'local';
const config = environments[currentEnv];

export default defineConfig({
  use: {
    baseURL: config.baseURL,
    extraHTTPHeaders: {
      'X-API-Base': config.apiURL,
    },
  },
});

Exécution :

TEST_ENV=staging npx playwright test
TEST_ENV=production npx playwright test --grep @smoke

Feature flags dans les tests

Quand votre application utilise des feature flags, les tests peuvent avoir besoin de se comporter différemment selon ce qui est activé :

const NEW_CHECKOUT = process.env.FEATURE_NEW_CHECKOUT === 'true';

test('flux de paiement', async ({ page }) => {
  await page.goto('/checkout');

  if (NEW_CHECKOUT) {
    // Tester la nouvelle UI de paiement
    await expect(page.getByTestId('new-checkout-form')).toBeVisible();
  } else {
    // Tester l'ancienne UI de paiement
    await expect(page.getByTestId('legacy-checkout-form')).toBeVisible();
  }
});

Mieux : des fichiers de test séparés par état de feature flag, contrôlés par des projets Playwright :

projects: [
  {
    name: 'new-checkout',
    testMatch: '**/checkout-new/**',
    use: { extraHTTPHeaders: { 'X-Feature-New-Checkout': 'true' } },
  },
  {
    name: 'legacy-checkout',
    testMatch: '**/checkout-legacy/**',
  },
],

Configuration CI/CD

Exemple GitHub Actions avec une gestion correcte des secrets :

# .github/workflows/tests.yml
env:
  # Non sensible — utilisez vars, visible dans les logs
  BASE_URL: ${{ vars.STAGING_URL }}
  TEST_ENV: staging

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Lancer les tests
        env:
          # Sensible — utilisez secrets, masqué dans les logs
          TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
          TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
          API_KEY: ${{ secrets.API_KEY }}
        run: npx playwright test

Distinction clé : vars. pour la configuration non sensible (visible dans les logs), secrets. pour les identifiants et clés (masqué dans les logs, jamais affiché).

Valider la configuration au démarrage de la suite

Utilisez le global setup pour valider l'environnement avant l'exécution des tests :

// global-setup.ts
export default async function globalSetup() {
  const required = ['TEST_USER_EMAIL', 'TEST_USER_PASSWORD', 'BASE_URL'];
  const missing = required.filter(key => !process.env[key]);

  if (missing.length > 0) {
    throw new Error(
      `Variables d'environnement manquantes :\n${missing.map(k => `  - ${k}`).join('\n')}\n\n` +
      `Copiez .env.example vers .env.local et remplissez les valeurs.`
    );
  }

  console.log(`Tests lancés contre : ${process.env.BASE_URL}`);
}

Cela échoue rapidement avec un message clair plutôt que de laisser le premier test échouer avec une erreur de locator confuse.

→ See also: Fichier de Configuration Playwright Expliqué: Toutes les Options à Connaître | Configuration d'Environnement Playwright: Local, Staging et Production | GitHub Actions pour Tests Playwright: La Configuration Complète (2026)