Playwright Basics: Complete Beginner Tutorial for QA Automation

Introduction: What Are Playwright Basics and Why Do They Matter?

If you are new to test automation, learning Playwright basics gives you a practical foundation for automating modern web applications.

Playwright is a browser automation and end-to-end testing framework that supports Chromium, Firefox, and WebKit. It can automate actions such as opening pages, clicking buttons, entering text, submitting forms, handling popups, working with frames, and validating application behavior.

For QA Automation Engineers and SDETs, the basics are especially important because advanced Playwright frameworks are built on these fundamentals.

Before learning Page Object Model, fixtures, API testing, parallel execution, or CI/CD, you should understand:

This Playwright Basics Tutorial for Beginners explains each concept with practical Playwright TypeScript examples.


What Is Playwright?

Playwright is an open-source automation and testing framework originally developed by Microsoft.

It can automate modern web applications across multiple browser engines.

A basic test looks like this:

import { test, expect } from ‘@playwright/test’;

test(‘verify Playwright homepage’, async ({ page }) => {

  await page.goto(‘https://playwright.dev/’);

  await expect(page).toHaveTitle(/Playwright/);

});

This small example already demonstrates several important Playwright concepts:

  • test() defines a test.
  • page represents a browser page.
  • goto() navigates to a URL.
  • expect() verifies application behavior.
  • toHaveTitle() is an assertion.

Understanding these building blocks is the foundation of Playwright automation testing.


Playwright Architecture and Core Concepts

One of the most important parts of learning Playwright basics for beginners is understanding how the framework is organized.

A simplified architecture looks like this:

Playwright Test

      |

      +—- Browser

              |

              +—- Browser Context

                       |

                       +—- Page

                              |

                              +—- Locator

                              |

                              +—- Assertions

Let’s understand each term.

Browser

The browser represents a browser engine such as Chromium, Firefox, or WebKit.

Browser Context

A browser context is an isolated browser session.

It is similar to creating a fresh browser profile without launching an entirely separate browser process.

Contexts help keep tests isolated.

Page

A page represents a browser tab.

For example:

await page.goto(‘https://example.com’);

Locator

A locator identifies an element on the page.

page.getByRole(‘button’, { name: ‘Login’ });

Assertion

An assertion verifies expected behavior.

await expect(page).toHaveTitle(/Dashboard/);

Test

A test contains the actions and validations for a particular scenario.

Fixture

A fixture provides reusable test resources.

The built-in page fixture is one of the most commonly used Playwright fixtures.

Reporter

A reporter controls how test results are displayed or stored.

Playwright supports reporters such as the HTML reporter.


Playwright Browsers and Supported Environments

Playwright supports three major browser engines:

BrowserPlaywright project
ChromiumChrome/Chromium-based testing
FirefoxFirefox testing
WebKitSafari engine testing

This is useful because QA teams can test the same application across different browser engines.

Playwright can also run in:

  • Windows
  • Linux
  • macOS
  • CI/CD environments
  • Containers such as Docker

For beginners, start with Chromium and then add Firefox and WebKit when you understand the fundamentals.


Installing Playwright and Creating a Project

Step 1: Install Node.js

Playwright Test works with Node.js.

Verify your installation:

node –version

npm –version

Step 2: Create a Playwright project

Run:

npm init playwright@latest

The setup wizard will ask several questions.

For this tutorial, choose:

TypeScript

You can choose a test directory such as:

tests

Step 3: Install browsers

If required, run:

npx playwright install

Step 4: Verify Playwright

npx playwright –version

Your project is now ready.


Understanding playwright.config.ts

The playwright.config.ts file controls important test settings.

A simple configuration looks like this:

import { defineConfig, devices } from ‘@playwright/test’;

export default defineConfig({

  testDir: ‘./tests’,

  use: {

    baseURL: ‘https://example.com’,

    headless: true,

    screenshot: ‘only-on-failure’,

    trace: ‘on-first-retry’,

  },

  projects: [

    {

      name: ‘chromium’,

      use: { …devices[‘Desktop Chrome’] },

    },

  ],

});

Important settings include:

testDir

Specifies where tests are stored.

testDir: ‘./tests’

baseURL

Allows shorter navigation commands.

baseURL: ‘https://example.com’

Then:

await page.goto(‘/login’);

instead of:

await page.goto(‘https://example.com/login’);

headless

Controls whether the browser is visible.

headless: true

screenshot

Controls screenshot behavior.

screenshot: ‘only-on-failure’

trace

Controls trace collection.

trace: ‘on-first-retry’

For beginners, avoid changing too many configuration options until you understand what each one does.


Writing Your First Playwright Test

Concept

A Playwright test generally contains:

  1. Test definition
  2. Browser interaction
  3. Assertion

Code

Create:

tests/homepage.spec.ts

Add:

import { test, expect } from ‘@playwright/test’;

test(‘verify Playwright homepage’, async ({ page }) => {

  await page.goto(‘https://playwright.dev/’);

  await expect(page).toHaveTitle(/Playwright/);

  await expect(

    page.getByRole(‘heading’, { name: /Playwright enables reliable/ })

  ).toBeVisible();

});

Explanation

The test:

  1. Opens Playwright’s website.
  2. Checks the title.
  3. Finds a heading using its accessible role.
  4. Verifies that the heading is visible.

Expected Result

The test passes if the title and heading meet the expectations.

Run:

npx playwright test

To see the browser:

npx playwright test –headed

Best Practice

Use meaningful test names:

test(‘valid user can log in successfully’, async ({ page }) => {

});

instead of:

test(‘test1’, async ({ page }) => {

});


Playwright Locators and Element Interactions

Locators are a fundamental part of Playwright testing framework basics.

A locator tells Playwright which element you want to interact with.

getByRole()

Use accessible roles where possible.

await page.getByRole(‘button’, { name: ‘Login’ }).click();

getByLabel()

Excellent for form fields.

await page.getByLabel(‘Username’).fill(‘admin’);

getByText()

Useful for visible text.

await page.getByText(‘Welcome’).click();

getByPlaceholder()

await page.getByPlaceholder(‘Enter email’).fill(‘user@example.com’);

getByTestId()

await page.getByTestId(‘submit-button’).click();

CSS Locator

await page.locator(‘#username’).fill(‘admin’);

Locator Best Practice

Prefer:

page.getByRole(‘button’, { name: ‘Submit’ })

over fragile selectors such as:

page.locator(‘div.container > div:nth-child(2) > button’)

Stable, user-facing locators generally make tests easier to maintain.


Assertions and Auto-Waiting

Assertions are another essential part of Playwright basics.

They answer questions such as:

  • Is the element visible?
  • Is the button enabled?
  • Does the page have the correct title?
  • Is the URL correct?
  • Does the text match?
  • Is a checkbox selected?

Examples:

await expect(page).toHaveTitle(/Playwright/);

await expect(page).toHaveURL(/playwright/);

await expect(page.getByRole(‘button’)).toBeVisible();

await expect(page.getByText(‘Success’)).toHaveText(‘Success’);

What Is Auto-Waiting?

Playwright automatically waits for many actionability conditions before performing actions.

For example:

await page.getByRole(‘button’, { name: ‘Submit’ }).click();

Playwright can wait for the button to become actionable instead of requiring you to manually pause the test.

Avoid unnecessary code such as:

await page.waitForTimeout(5000);

Instead, use an assertion:

await expect(page.getByText(‘Order completed’)).toBeVisible();

This is more reliable because the test waits for the actual application condition.


Navigation, Forms, Buttons, Dropdowns, and Checkboxes

These are the most common browser automation operations.

Navigation

await page.goto(‘https://example.com’);

await page.goBack();

await page.goForward();

await page.reload();

Clicking

await page.getByRole(‘button’, { name: ‘Submit’ }).click();

Typing

await page.getByLabel(‘Email’).fill(‘user@example.com’);

Form Submission

await page.getByLabel(‘Username’).fill(‘admin’);

await page.getByLabel(‘Password’).fill(‘Password123’);

await page.getByRole(‘button’, { name: ‘Login’ }).click();

Dropdown

For a standard HTML <select>:

await page.getByLabel(‘Country’).selectOption(‘IN’);

Checkbox

await page.getByLabel(‘Accept Terms’).check();

Verify it:

await expect(page.getByLabel(‘Accept Terms’)).toBeChecked();


Real-World Login Automation Example

A login scenario is one of the best Playwright basics examples for QA engineers.

Concept

Automate a typical username/password login flow.

Code

import { test, expect } from ‘@playwright/test’;

test(‘user can log in’, async ({ page }) => {

  await page.goto(‘https://example.com/login’);

  await page.getByLabel(‘Username’).fill(‘testuser’);

  await page.getByLabel(‘Password’).fill(‘Password123’);

  await page.getByRole(‘button’, { name: ‘Login’ }).click();

  await expect(

    page.getByRole(‘heading’, { name: ‘Dashboard’ })

  ).toBeVisible();

});

Explanation

The test:

  1. Opens the login page.
  2. Enters the username.
  3. Enters the password.
  4. Clicks Login.
  5. Verifies the Dashboard.

Expected Result

The test passes when the Dashboard appears.

Best Practice

Never commit real credentials into your Git repository. Use environment variables or CI/CD secrets.


Handling Alerts, Popups, Frames, and Multiple Pages

Handling Alerts

Browser dialogs can be handled with a dialog event:

page.on(‘dialog’, async dialog => {

  console.log(dialog.message());

  await dialog.accept();

});

await page.getByRole(‘button’, { name: ‘Delete’ }).click();

Handling Popups

Suppose a button opens another page:

const popupPromise = page.waitForEvent(‘popup’);

await page.getByRole(‘link’, { name: ‘Open Report’ }).click();

const popup = await popupPromise;

await popup.waitForLoadState();

await expect(popup).toHaveTitle(/Report/);

Handling Frames

Use frameLocator():

const frame = page.frameLocator(‘#payment-frame’);

await frame.getByLabel(‘Card Number’).fill(‘4111111111111111’);

Multiple Pages

You can access pages through the browser context:

const pages = page.context().pages();

console.log(pages.length);

These features become particularly useful in real-world applications containing payment widgets, authentication flows, external links, and embedded content.


Screenshots, Videos, Trace Viewer, and Reports

Debugging is a critical automation skill.

Taking a Screenshot

await page.screenshot({

  path: ‘screenshots/home.png’,

  fullPage: true

});

Screenshot on Failure

Configure:

use: {

  screenshot: ‘only-on-failure’

}

This prevents unnecessary screenshots for successful tests.

Trace

A trace can provide detailed information about a test execution.

For example:

use: {

  trace: ‘on-first-retry’

}

After a failure and retry, you can inspect the generated trace using Playwright’s trace tooling.

HTML Report

Run:

npx playwright show-report

The report helps you inspect:

  • Test status
  • Duration
  • Errors
  • Screenshots
  • Traces
  • Test steps

Best Practice

Do not simply rerun a failed test repeatedly. Investigate the error, locator, application state, screenshot, and trace.


Test Hooks, Fixtures, and Basic Test Organization

Hooks help organize setup and cleanup.

import { test, expect } from ‘@playwright/test’;

test.describe(‘Login Tests’, () => {

  test.beforeEach(async ({ page }) => {

    await page.goto(‘https://example.com/login’);

  });

  test(‘valid login’, async ({ page }) => {

    await page.getByLabel(‘Username’).fill(‘admin’);

    await page.getByLabel(‘Password’).fill(‘Password123’);

    await page.getByRole(‘button’, { name: ‘Login’ }).click();

    await expect(page.getByText(‘Dashboard’)).toBeVisible();

  });

});

Common hooks include:

  • beforeEach
  • afterEach
  • beforeAll
  • afterAll

Fixtures

The page object is a built-in fixture:

test(‘example’, async ({ page }) => {

  await page.goto(‘https://example.com’);

});

You can later create custom fixtures for:

  • Login sessions
  • Test data
  • API clients
  • Page objects
  • Database utilities

Introduction to Page Object Model

Page Object Model, or POM, is a design pattern for organizing automation code.

Instead of placing every locator inside the test, create a class.

LoginPage.ts

import { Page } from ‘@playwright/test’;

export class LoginPage {

  constructor(private page: Page) {}

  username = this.page.getByLabel(‘Username’);

  password = this.page.getByLabel(‘Password’);

  loginButton = this.page.getByRole(‘button’, { name: ‘Login’ });

  async login(username: string, password: string) {

    await this.username.fill(username);

    await this.password.fill(password);

    await this.loginButton.click();

  }

}

Test

import { test, expect } from ‘@playwright/test’;

import { LoginPage } from ‘../pages/LoginPage’;

test(‘login using Page Object Model‘, async ({ page }) => {

  const loginPage = new LoginPage(page);

  await page.goto(‘https://example.com/login’);

  await loginPage.login(‘admin’, ‘Password123’);

  await expect(page.getByText(‘Dashboard’)).toBeVisible();

});

Why Use POM?

POM provides:

  • Reusable page actions
  • Centralized locators
  • Cleaner tests
  • Easier maintenance
  • Better scalability

For beginners, start with simple POM classes. Do not create an overly complicated framework before understanding the fundamentals.


Cross-Browser Testing and Parallel Execution Basics

One benefit of Playwright is cross-browser testing.

A configuration can define multiple projects:

import { defineConfig, devices } from ‘@playwright/test’;

export default defineConfig({

  testDir: ‘./tests’,

  projects: [

    {

      name: ‘chromium’,

      use: { …devices[‘Desktop Chrome’] },

    },

    {

      name: ‘firefox’,

      use: { …devices[‘Desktop Firefox’] },

    },

    {

      name: ‘webkit’,

      use: { …devices[‘Desktop Safari’] },

    },

  ],

});

Run only Chromium:

npx playwright test –project=chromium

Run Firefox:

npx playwright test –project=firefox

Playwright Test also supports parallel execution.

Parallel testing is useful for large suites, but tests should not depend on one another.

Bad design:

Test A creates data

       ↓

Test B uses Test A’s data

Better design:

Test A → independent data

Test B → independent data

Test C → independent data

Independent tests are easier to run in parallel.


Basic CI/CD Integration

A basic CI/CD workflow looks like this:

Code Push

   ↓

Install Node dependencies

   ↓

Install Playwright browsers

   ↓

Run tests

   ↓

Generate report

   ↓

Publish artifacts

A simple GitHub Actions workflow:

name: Playwright Tests

on:

  push:

    branches: [main]

  pull_request:

    branches: [main]

jobs:

  test:

    runs-on: ubuntu-latest

    steps:

      – uses: actions/checkout@v6

      – uses: actions/setup-node@v6

        with:

          node-version: lts/*

      – run: npm ci

      – run: npx playwright install –with-deps

      – run: npx playwright test

      – uses: actions/upload-artifact@v5

        if: ${{ !cancelled() }}

        with:

          name: playwright-report

          path: playwright-report/

For a beginner, understanding this pipeline is enough initially. Later, learn:

  • Environment variables
  • Secrets
  • Test sharding
  • Docker
  • Retry strategies
  • Artifact management

Common Playwright Beginner Errors and Solutions

Error 1: Browser executable missing

Try:

npx playwright install

Error 2: Locator not found

Check:

  • Is the locator correct?
  • Is the element inside an iframe?
  • Has the page loaded?
  • Is the element dynamically rendered?
  • Is the accessible name correct?

Use:

npx playwright test –debug

Error 3: Test passes locally but fails in CI

Check:

  • Browser installation
  • Environment variables
  • Base URL
  • Timing
  • Test isolation
  • CI-specific dependencies

Avoid solving every CI failure by adding long waits.

Error 4: Strict mode violation

This often means your locator matches multiple elements.

Instead of using a broad locator:

page.getByText(‘Submit’)

make it more specific:

page.getByRole(‘button’, { name: ‘Submit’ })

Error 5: Flaky tests

Look for:

  • Fragile locators
  • Shared test data
  • Race conditions
  • Hard-coded waits
  • External dependencies
  • Incorrect synchronization

Playwright Best Practices

A strong beginner framework follows a few simple principles.

1. Prefer resilient locators

Use:

getByRole()

getByLabel()

getByTestId()

before fragile selectors.

2. Avoid hard waits

Prefer:

await expect(locator).toBeVisible();

over:

await page.waitForTimeout(3000);

3. Keep tests independent

Each test should be able to run by itself.

4. Use Page Object Model when appropriate

Do not duplicate the same page interactions throughout dozens of tests.

5. Keep credentials secure

Use environment variables and CI/CD secrets.

6. Use meaningful test names

Good:

valid user can submit payment

Poor:

test payment

7. Use debugging artifacts intelligently

Screenshots, traces, and reports are especially valuable when tests execute in CI.

8. Learn TypeScript

Playwright TypeScript becomes much easier when you understand:

  • Variables
  • Functions
  • Classes
  • Interfaces
  • Types
  • Async/await
  • Imports and exports

Playwright Interview Questions With Answers

1. What are Playwright basics?

Playwright basics are the core concepts needed to automate web applications, including browsers, contexts, pages, locators, actions, assertions, fixtures, configuration, and test execution.

2. What is Playwright?

Playwright is an open-source browser automation and end-to-end testing framework.

3. What browsers does Playwright support?

Playwright supports Chromium, Firefox, and WebKit.

4. What is a browser context?

A browser context is an isolated browser session that helps keep tests independent.

5. What is a page in Playwright?

A page represents a browser tab.

6. What is a locator?

A locator identifies an element that Playwright should interact with or validate.

Example:

page.getByRole(‘button’, { name: ‘Login’ })

7. What is auto-waiting?

Auto-waiting allows Playwright to wait for required actionability conditions before performing actions.

8. What is a fixture?

A fixture provides reusable test resources such as the built-in page fixture.

9. How do you execute Playwright tests?

npx playwright test

10. How do you execute a test in headed mode?

npx playwright test –headed

11. How do you debug Playwright tests?

You can use headed execution, the Playwright Inspector, screenshots, traces, and HTML reports.

12. Why is Page Object Model used?

POM separates page interaction logic from test logic and improves maintainability and reuse.


Playwright Learning Roadmap for Beginners

A practical learning roadmap is:

Stage 1: Programming Fundamentals

Learn:

  • JavaScript basics
  • TypeScript basics
  • Async/await
  • Functions
  • Classes
  • Arrays and objects

Stage 2: Playwright Fundamentals

Learn:

  • Installation
  • Configuration
  • Browser
  • Context
  • Page
  • Locators
  • Actions
  • Assertions

Stage 3: Web Automation

Practice:

  • Login
  • Forms
  • Dropdowns
  • Checkboxes
  • Tables
  • Dynamic elements
  • Alerts
  • Frames
  • Popups
  • Multiple pages

Stage 4: Framework Development

Learn:

Stage 5: Advanced Automation

Move into:

Stage 6: DevOps

Learn:

Stage 7: Interview Preparation

Practice explaining:

For QA Automation and SDET roles, combine Playwright with API testing, SQL, Git, CI/CD, JavaScript/TypeScript, and strong software testing fundamentals.


Related Playwright Tutorials to Learn Next

Once you understand Playwright basics, continue with:

These topics can take you from basic browser automation to designing a complete automation framework.


FAQs About Playwright Basics

What are Playwright basics?

Playwright basics include installation, project setup, browser and page concepts, locators, browser actions, assertions, auto-waiting, test configuration, debugging, and reporting.

How do I get started with Playwright basics?

Install Node.js, create a Playwright TypeScript project using npm init playwright@latest, install the browsers, create a test, and execute it using npx playwright test.

Is Playwright easy for beginners?

Yes. The framework provides a readable API and built-in capabilities such as auto-waiting, assertions, browser contexts, tracing, and reporting.

What language should beginners use with Playwright?

TypeScript is an excellent option for beginners who want to build modern automation frameworks. JavaScript, Python, Java, and .NET are also supported.

What is the difference between Playwright and Selenium?

Both automate browsers. Playwright provides a modern testing experience with features such as built-in auto-waiting, browser contexts, tracing, and integrated test execution. Selenium has a mature ecosystem and extensive enterprise adoption.

Does Playwright require coding knowledge?

Yes. Basic programming knowledge is useful. For Playwright TypeScript, beginners should understand variables, functions, classes, async/await, and basic TypeScript syntax.

Can Playwright be used for CI/CD?

Yes. Playwright tests can run in CI/CD platforms such as GitHub Actions and other continuous integration systems.

What should I learn after Playwright basics?

Learn Page Object Model, fixtures, authentication, API testing, reporting, parallel execution, CI/CD, Docker, and advanced debugging.

Leave a Comment

Your email address will not be published. Required fields are marked *