Skip to main content

The Master Switch: Deep Dive into Playwright's - playwright.config.js


When you embark on a Playwright test automation journey, you quickly encounter playwright.config.js. This seemingly humble JavaScript file is, in fact, the central control panel for your entire test suite. It's where you configure browsers, define parallel execution, set timeouts, integrate reporters, and manage various test environments.

Understanding playwright.config.js is crucial because it dictates the behavior of your tests without needing to modify individual test files. This makes your framework incredibly flexible, scalable, and adaptable to different testing needs.

Let's unravel the key sections of this powerful configuration file.

What is playwright.config.js?

At its core, playwright.config.js is a Node.js module that exports a configuration object. Playwright's test runner reads this file to understand:

  • Where to find your tests.

  • Which browsers to run tests on.

  • How many tests to run in parallel.

  • How to report test results.

  • Various timeouts and debugging options.

  • And much more!

Basic Structure

When you initialize a Playwright project (e.g., npm init playwright@latest), a playwright.config.js file is generated for you. It typically looks something like this:

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

export default defineConfig({
  testDir: './tests', // Where your test files are located
  fullyParallel: true, // Run tests in files in parallel
  forbidOnly: process.env.CI ? true : false, // Disallow .only on CI
  retries: process.env.CI ? 2 : 0, // Number of retries on CI
  workers: process.env.CI ? 1 : undefined, // Number of parallel workers on CI
  reporter: 'html', // Reporter to use

  use: {
    // Base URL to use in tests like `await page.goto('/')`.
    baseURL: 'http://127.0.0.1:3000',
    trace: 'on-first-retry', // Collect trace when retrying a failed test
  },

  /* Configure projects for browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],

  /* Run your local dev server before starting the tests */
  // webServer: {
  //   command: 'npm run start',
  //   url: 'http://127.0.0.1:3000',
  //   reuseExistingServer: !process.env.CI,
  // },
});

Let's break down the most important configuration options.

Key Configuration Options Explained

1. testDir

  • Purpose: Specifies the directory where Playwright should look for your test files.

  • Example: testDir: './tests', (looks for tests in a folder named tests at the root).

2. Execution Control & Parallelization

  • fullyParallel: boolean

    • Purpose: If true, tests in different test files will run in parallel.

    • Default: false

  • forbidOnly: boolean

    • Purpose: If true, fails the test run if any test uses .only(). Essential for CI to prevent accidentally committed focused tests.

    • Example: forbidOnly: process.env.CI ? true : false, (only forbid on CI).

  • retries: number

    • Purpose: The number of times to retry a failed test. Highly recommended for CI environments to mitigate flakiness.

    • Example: retries: 2, (retry twice if a test fails).

  • workers: number

    • Purpose: Defines the maximum number of worker processes that Playwright can use to run tests in parallel.

    • Default: About 1/2 of your CPU cores.

    • Example: workers: 4, or workers: process.env.CI ? 1 : undefined, (run sequentially on CI for specific reasons, like database contention).

3. reporter

  • Purpose: Configures how test results are reported. You can specify single or multiple reporters.

  • Common Built-in Reporters:

    • 'list': Prints a list of tests and their status (default).

    • 'dot': Prints a dot for each test (pass/fail).

    • 'line': A more verbose list reporter.

    • 'html': Generates a rich, interactive HTML report (highly recommended for local viewing).

    • 'json': Exports results as a JSON file.

    • 'junit': Exports results in JUnit XML format (common for CI/CD tools).

  • Example (multiple reporters):

    JavaScript
    reporter: [
      ['list'],
      ['html', { open: 'never' }], // Don't open automatically after run
      ['json', { outputFile: 'test-results.json' }],
    ],
    

4. use

This is a global configuration object applied to all tests unless overridden by projects. It contains browser-specific settings and test runtime options.

  • baseURL: string

    • Purpose: The base URL for your application. Allows you to use relative paths like await page.goto('/') in your tests.

    • Example: baseURL: 'http://localhost:8080',

  • headless: boolean

    • Purpose: If true, browsers run in headless mode (without a UI). Ideal for CI. If false, browsers launch with a visible UI.

    • Default: true in CI, false otherwise.

    • Example: headless: true,

  • viewport: { width: number, height: number }

    • Purpose: Sets the browser viewport size.

    • Example: viewport: { width: 1280, height: 720 },

  • Timeouts (actionTimeout, navigationTimeout, expect.timeout)

    • actionTimeout: number: Maximum time for any action (click, fill, etc.) to complete. Includes auto-waiting.

    • navigationTimeout: number: Maximum time for a navigation to occur.

    • expect.timeout: number: Default timeout for expect() assertions (Web-First Assertions).

    • Example:

      JavaScript
      actionTimeout: 10000, // 10 seconds
      navigationTimeout: 30000, // 30 seconds
      expect: { timeout: 5000 }, // 5 seconds for assertions
      
  • Artifacts on Failure (screenshot, video, trace)

    • Purpose: Configure what artifacts Playwright saves when a test fails. Crucial for debugging.

    • screenshot: 'off', 'on', 'only-on-failure'.

    • video: 'off', 'on', 'retain-on-failure'.

    • trace: 'off', 'on', 'retain-on-failure', 'on-first-retry'. on-first-retry is a good balance.

    • Example:

      JavaScript
      screenshot: 'only-on-failure',
      video: 'retain-on-failure',
      trace: 'on-first-retry',
      
  • testIdAttribute: string

    • Purpose: Defines the data-* attribute that Playwright's getByTestId() locator should look for. Connects directly to our previous discussion on robust locators!

    • Default: 'data-testid'

    • Example: testIdAttribute: 'data-qa-id', (if your developers use data-qa-id).

5. projects

  • Purpose: Defines different test configurations (projects). This is how you run tests across multiple browsers, device emulations, or even different environments (e.g., staging vs. production API tests). Each project can override global use settings.

  • Key usage: Often combined with devices (Playwright's predefined device presets).

  • Example (Desktop & Mobile):

    JavaScript
    projects: [
      {
        name: 'desktop_chromium',
        use: { ...devices['Desktop Chrome'] },
      },
      {
        name: 'mobile_safari',
        use: { ...devices['iPhone 12'] }, // Emulate iPhone 12
      },
      // You can also define projects for different environments:
      // {
      //   name: 'api_staging',
      //   testMatch: /.*\.api\.spec\.js/, // Run only API tests
      //   use: { baseURL: 'https://staging.api.example.com' },
      // },
    ],
    

    To run specific projects: npx playwright test --project=desktop_chromium

6. webServer

  • Purpose: Automatically starts a local development server before tests run and stops it afterwards. Ideal for testing front-end applications that need to be served.

  • Example:

    JavaScript
    webServer: {
      command: 'npm run start', // Command to start your dev server
      url: 'http://localhost:3000', // URL the server should be available at
      reuseExistingServer: !process.env.CI, // Don't start if already running (useful locally)
      timeout: 120 * 1000, // Timeout for the server to start (2 minutes)
    },
    

7. defineConfig

  • Purpose: (Used implicitly in the default template) A helper function that provides type safety and better IntelliSense/autocompletion for your configuration object, especially useful in TypeScript. While not strictly required for JavaScript, it's good practice.

  • Example: export default defineConfig({ ... });

Tips and Best Practices

  1. Start Simple: Don't over-configure initially. Add options as your needs evolve.

  2. Leverage projects: Use projects extensively for managing different test dimensions (browsers, devices, environments).

  3. Use Environment Variables: Parameterize sensitive data or environment-specific values using process.env.

  4. Manage Timeouts Wisely: Adjust timeouts based on your application's typical responsiveness, but avoid excessively long timeouts which can hide performance issues.

  5. Artifacts for Debugging: Always configure screenshot, video, and trace on failure, especially for CI runs. They are invaluable for debugging.

  6. testIdAttribute: Collaborate with developers to implement a consistent data-testid strategy in your application and configure it here.

Conclusion

playwright.config.js is much more than just a settings file; it's a powerful tool that enables you to precisely control your test execution, improve debugging, and build a highly adaptable test automation framework. By understanding and effectively utilizing its myriad options, you can tailor Playwright to fit the exact needs of your project, ensuring robust, efficient, and reliable test automation.

Comments

Popular posts from this blog

How to Inspect Disappearing Elements Using "Emulate a Focused Page" in Chrome DevTools

As web developers, we often encounter frustrating scenarios where elements like dropdowns, tooltips, or custom select menus vanish the moment we try to inspect them in Chrome DevTools. This happens because these elements are often designed to disappear when they lose focus or the mouse moves away. Fortunately, Chrome DevTools provides a powerful feature called "Emulate a focused page" that lets you freeze the page's focus state, making it much easier to debug these elusive elements. The Challenge of Disappearing Elements 👻 Imagine you're styling a complex navigation menu with sub-menus that appear on hover. When you try to right-click and "Inspect" one of these sub-menus, it vanishes! This is a classic example of an element losing its active state because DevTools gains focus, causing the element's blur or focusout event to trigger its disappearance. Traditional methods like trying to quickly click and inspect often fail, leading to wasted time and f...

ISTQB CTFL Mock Test

ISTQB CTFL Interactive Mock Test Ready to ace your ISTQB Certified Tester Foundation Level (CTFL) exam? Practice is paramount! While studying the official syllabus and glossary is essential, testing your knowledge with mock exams is the best way to prepare for the actual exam format, question types, and time pressure. This blog post brings you a 40-question mock test designed to mirror the structure and difficulty of the real ISTQB CTFL exam. Take your time, answer each question to the best of your ability, and then use the provided answer key to check your performance. Aim to complete these 40 questions within 60 minutes, just like the actual exam. Important Note on Interactivity: While it would be fantastic to offer a fully interactive quiz here with real-time scoring and highlighting, this blog post format primarily delivers text. To experience an interactive version with automated scoring and feedback (like showing marks and highlighting wrong answers in r...

Selenium vs. Playwright: A Deep Dive into Waiting Concepts

  In the world of web automation, "waiting" is not just a pause; it's a strategic synchronization mechanism. Web applications are dynamic: elements appear, disappear, change state, or load asynchronously. Without proper waiting strategies, your automation scripts will frequently fail with "element not found" or "element not interactable" errors, leading to flaky and unreliable tests. Let's explore how Selenium and Playwright approach this fundamental challenge. The Challenge: Why Do We Need Waits? Imagine a user interacting with a webpage. They don't click a button the exact instant it appears in the HTML. They wait for it to be visible, stable, and ready to receive clicks. Automation tools must mimic this human behavior. If a script tries to interact with an element before it's fully loaded or clickable, it will fail. Waits bridge the gap between your script's execution speed and the web application's loading time. Selenium'...