Back

Getting Started with UI Testing in Playwright

Getting Started with UI Testing in Playwright

UI testing is a critical part of frontend development, ensuring your web applications work correctly from the user’s perspective. Playwright, Microsoft’s open-source automation framework, has emerged as a powerful tool for UI testing that’s both developer-friendly and robust. If you’ve heard about Playwright but haven’t tried it yet, this guide will show you how it works and whether it fits into your current workflow.

Key Takeaways

  • Playwright provides cross-browser testing with a single API for Chrome, Firefox, and Safari
  • Auto-waiting and isolated test environments reduce flaky tests
  • Built-in debugging tools like Inspector and Trace Viewer simplify troubleshooting
  • Supports responsive design testing, visual comparisons, and component testing
  • Integrates easily with CI/CD pipelines for automated testing

What is Playwright and Why Use It for UI Testing?

Playwright is an end-to-end testing framework that enables you to write tests that run across all modern browsers (Chrome, Firefox, Safari) using a single API. Unlike other testing tools, Playwright was specifically designed for modern web applications with features that make UI testing more reliable and less flaky.

Key advantages for UI testing include:

  • Auto-waiting: Playwright automatically waits for elements to be actionable before performing operations
  • Isolation: Each test runs in a fresh browser context, preventing test interference
  • Cross-browser support: Write once, test everywhere with the same code
  • Modern web capabilities: Handles Shadow DOM, iframes, and modern web components
  • Powerful tooling: Built-in debugging tools like Playwright Inspector and Trace Viewer

Setting Up Playwright for UI Testing

Getting started with Playwright is straightforward. You’ll need Node.js installed, then you can set up a new project:

# Create a new directory for your project
mkdir playwright-ui-testing
cd playwright-ui-testing

# Initialize a new Playwright project
npm init playwright@latest

During setup, you’ll be prompted with a few questions. For UI testing, you can select TypeScript, add GitHub Actions workflow, and install browsers when prompted.

The installation creates a basic project structure with:

  • playwright.config.ts: Configuration file for your tests
  • tests directory: Where your test files will live
  • .github directory: CI configuration if you selected GitHub Actions

Writing Your First UI Test

Let’s write a simple UI test that verifies a product card appears correctly on an e-commerce site. Create a new file called product-ui.spec.ts in the tests directory:

import { test, expect } from '@playwright/test';

test('product card displays correctly', async ({ page }) => {
  // Navigate to the page
  await page.goto('https://demo-store.playwright.dev');
  
  // Find a product card
  const productCard = page.locator('.product-card').first();
  
  // Verify the product card is visible
  await expect(productCard).toBeVisible();
  
  // Verify it contains expected elements
  await expect(productCard.locator('.product-title')).toBeVisible();
  await expect(productCard.locator('.product-price')).toBeVisible();
  await expect(productCard.locator('button.add-to-cart')).toBeEnabled();
  
  // Extract and verify product information
  const title = await productCard.locator('.product-title').textContent();
  console.log(`Found product: ${title}`);
});

This test:

  1. Opens a demo store website
  2. Locates a product card
  3. Verifies that key elements are visible and enabled
  4. Extracts the product title (showing how you can scrape information)

Running UI Tests

To run your test, use the Playwright CLI:

npx playwright test product-ui.spec.ts

By default, Playwright runs tests in headless mode. To see the browser in action:

npx playwright test product-ui.spec.ts --headed

To run tests in a specific browser:

npx playwright test product-ui.spec.ts --project=chromium

Advanced UI Testing with Playwright

Testing Responsive Designs

Playwright makes it easy to test your UI across different screen sizes:

test('product card is responsive', async ({ page }) => {
  // Test on mobile viewport
  await page.setViewportSize({ width: 375, height: 667 });
  await page.goto('https://demo-store.playwright.dev');
  
  // Verify mobile layout
  await expect(page.locator('.mobile-menu-button')).toBeVisible();
  
  // Test on desktop viewport
  await page.setViewportSize({ width: 1280, height: 800 });
  
  // Verify desktop layout
  await expect(page.locator('.desktop-navigation')).toBeVisible();
});

Visual Testing

Playwright supports visual comparisons to catch unexpected UI changes:

test('product page visual test', async ({ page }) => {
  await page.goto('https://demo-store.playwright.dev/product/1');
  
  // Compare screenshot with baseline
  await expect(page).toHaveScreenshot('product-page.png');
});

The first time you run this test, it creates a baseline screenshot. On subsequent runs, it compares the current state with the baseline.

Testing Dynamic UI Elements

Modern web apps often have dynamic UI elements. Playwright handles these well:

test('add product to cart updates counter', async ({ page }) => {
  await page.goto('https://demo-store.playwright.dev');
  
  // Get initial cart count
  const cartCount = page.locator('.cart-count');
  await expect(cartCount).toHaveText('0');
  
  // Add product to cart
  await page.locator('.product-card button.add-to-cart').first().click();
  
  // Verify cart count updates
  await expect(cartCount).toHaveText('1');
});

Debugging UI Tests

When tests fail, Playwright offers powerful debugging tools:

Playwright Inspector

Launch the visual inspector to debug your tests:

PWDEBUG=1 npx playwright test product-ui.spec.ts

The inspector lets you:

  • Step through test execution
  • Inspect the DOM
  • View console logs
  • Explore network requests

Trace Viewer

Traces record detailed information about test execution:

// In your playwright.config.ts
export default defineConfig({
  use: {
    trace: 'on-first-retry', // Record traces on first retry of failed tests
  },
});

After a test fails, view the trace:

npx playwright show-trace test-results/product-ui-test-chromium/trace.zip

The trace viewer shows:

  • Screenshots at each step
  • DOM snapshots
  • Network activity
  • Console logs

Integrating Playwright UI Tests into Your Workflow

Running Tests in CI

Playwright works well with CI systems. For GitHub Actions, the setup wizard creates a workflow file that runs your tests on push and pull requests.

For other CI systems, you can use the Playwright Docker image:

# Example for GitLab CI
test:
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  script:
    - npm ci
    - npx playwright test
  artifacts:
    when: always
    paths:
      - playwright-report/
    expire_in: 1 week

Component Testing

Beyond page-level tests, Playwright also supports component testing for frameworks like React, Vue, and Svelte:

// Example for React component testing
import { test, expect } from '@playwright/experimental-ct-react';
import ProductCard from '../components/ProductCard';

test('ProductCard renders correctly', async ({ mount }) => {
  const component = await mount(
    <ProductCard 
      title="Test Product" 
      price="$19.99" 
      image="/test-image.jpg" 
    />
  );
  
  await expect(component).toContainText('Test Product');
  await expect(component).toContainText('$19.99');
  await expect(component.locator('button')).toBeEnabled();
});

FAQs

Playwright offers cross-browser support out of the box and handles multiple tabs and windows, which Cypress struggles with. Playwright also tends to have fewer limitations when testing across domains. However, Cypress has a more mature ecosystem and a user-friendly test runner interface.

No. Playwright is designed for end-to-end and integration testing. Unit tests with frameworks like Jest are still valuable for testing individual functions and components in isolation.

Playwright allows you to store authentication state and reuse it across tests. First, launch a browser, navigate to the login page, and perform the login steps by filling in the username and password fields and submitting the form. Once logged in, save the browser's storage state to a file, which contains the authentication data. In your actual tests, you can configure Playwright to use this stored authentication state so that you don't need to log in before every test. This approach speeds up your test runs and ensures consistency across sessions.

Yes, Playwright has built-in screenshot comparison capabilities. For more advanced visual testing, you can integrate with specialized tools like Percy or Applitools.

You can speed up your Playwright UI tests by running them in parallel, which is enabled by default. When developing, use the --project flag to run tests on specific browsers only. Reusing authentication state instead of logging in during every test also reduces execution time. Additionally, using component testing provides quicker feedback for individual UI components.

Conclusion

By incorporating Playwright into your testing strategy, you can build more reliable frontend applications with confidence that your UI works correctly across browsers and devices. Its auto-waiting mechanisms, isolation features, and powerful debugging tools address many common pain points in UI testing. Whether you’re testing responsive designs, visual appearance, or dynamic interactions, Playwright provides a comprehensive solution that integrates seamlessly with modern development workflows.

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers