Playwright Project Structure

After successfully initializing a Playwright project, a series of files and folders will be generated in your project directory. This chapter explains in detail the purpose of each part.


Overview of the initialized project structure

Runnpm init playwright@latestAfter that, the following structure will be generated in the project directory:

your-project/
├── playwright.config.ts      # Playwright 配置文件
├── package.json              # 项目依赖与脚本
├── package-lock.json         # 依赖锁定文件
├── tests/                    # 测试文件目录
│   └── example.spec.ts       # 示例测试文件
├── tests-examples/           # 更多示例测试(可选)
│   └── demo-todo-app.spec.ts
├── .github/                  # GitHub Actions 配置(可选)
│   └── workflows/
│       └── playwright.yml
└── node_modules/             # npm 依赖包

playwright.config.ts — Configuration file

This is the core configuration file for Playwright, controlling all aspects of the test run.

Example

// File path: playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  // Test file directory, relative to this configuration file
  testDir: './tests',

  // Run all tests fully in parallel
  fullyParallel: true,

  // If test.only is left in the source code, the build fails on CI
  forbidOnly: !!process.env.CI,

  // Retry 2 times on failure in CI environment, no retry locally
  retries: process.env.CI ? 2 : 0,

  // Use a single worker in CI environment, and the default multiple workers locally
  workers: process.env.CI ? 1 : undefined,

  // Use the HTML reporter
  reporter: 'html',

  // Configuration shared by all tests
  use: {
    // Base URL, just use relative paths in tests
    baseURL: 'http://localhost:3000',

    // Collect trace on failure retry
    trace: 'on-first-retry',
  },

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

  // Start a local development server before tests begin (optional)
  // webServer: {
  //   command: 'npm run start',
  //   url: 'http://localhost:3000',
  //   reuseExistingServer: !process.env.CI,
  // },
});

playwright.config.tsIt is the core entry point controlling Playwright behavior. Chapter 15 will explain each configuration option in detail.


package.json — Dependencies and scripts

After initialization,package.jsonPlaywright-related content will be added:

Example

{
  "devDependencies": {
    "@playwright/test": "^1.52.0"    // Playwright Test as a dev dependency
  },
  "scripts": {
    "test": "playwright test"         // You can directly run npm test
  }
}

You can also add more custom scripts:

Example

{
  "scripts": {
    "test": "playwright test",
    "test:ui": "playwright test --ui",
    "test:headed": "playwright test --headed",
    "test:chromium": "playwright test --project=chromium",
    "test:debug": "playwright test --debug",
    "codegen": "playwright codegen"
  }
}

tests/ directory — Test files

tests/This directory is the default location for test files (specified bytestDirthe configuration).

The initialized example test file is as follows:

Example

// File path: tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  // Navigate to the Playwright website
  await page.goto('https://playwright.dev/');

  // Assert that the page title contains "Playwright"
  await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
  // Navigate to the Playwright website
  await page.goto('https://playwright.dev/');

  // Click the "Get started" link
  await page.getByRole('link', { name: 'Get started' }).click();

  // Assert that the heading "Installation" appears on the page
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

Naming convention for test files: use.spec.ts(TypeScript) or.spec.js(JavaScript) suffix.


tests-examples/ directory — More examples

If you chose to include example tests during initialization,tests-examples/then the directory will contain a more complete test example:

demo-todo-app.spec.tsIt demonstrates complete test scenarios for a real Todo application, including adding tasks, toggling completion status, filtering functionality, and more.

This is a great learning reference. You can run it to see the effect:

npx playwright test tests-examples/

.github/workflows/ — CI configuration

If you chose to add GitHub Actions during initialization,.github/workflows/playwright.ymlthe file will be generated automatically.

This workflow automatically runs Playwright tests every time code is pushed or a PR is created.


Browser storage location

The browser binaries installed by Playwright are not in the project directory, but are stored in the operating system cache directory:

Operating systemBrowser storage path
macOS
~/Library/Caches/ms-playwright/
Windows
%USERPROFILE%\AppData\Local\ms-playwright\
Linux
~/.cache/ms-playwright/

You can also set a custom storage path:

# 设置浏览器安装路径
export PLAYWRIGHT_BROWSERS_PATH=/your/custom/path
npx playwright install

node_modules/ — Dependency packages

Playwright's core dependencies@playwright/testare installednode_modules/in the node_modules/ directory.

The dependency internally contains the complete runtime of Playwright, including the protocol layer for communicating with browsers.

In addition to the Node.js packages installed via npm, Playwright also depends on browser binaries (stored in the system cache); both are indispensable.

Other extensions