Getting Started with Playwright Automation: A Beginner's Guide

November 22, 2024

Playwright
Automation
Testing
Tutorial
Beginner

Getting Started with Playwright Automation: A Beginner's Guide

Welcome to the world of browser automation! If you're looking to automate web testing or browser tasks, Playwright is an excellent choice. This guide will take you from zero to running your first automated tests.

What is Playwright?

Playwright is a modern automation framework that lets you:

  • 🌐 Control browsers programmatically
  • ✅ Write automated tests
  • 📸 Take screenshots and videos
  • 🔍 Scrape web data
  • 🤖 Automate repetitive browser tasks

It supports Chromium, Firefox, and WebKit - all with a single API!

Why Choose Playwright?

Compared to Selenium:

  • Faster: Auto-waiting and smarter selectors
  • 🎯 More Reliable: Built-in retry logic
  • 🛠️ Better DX: Excellent documentation and tooling
  • 🎭 Modern: Async by design

Key Features:

  • Cross-browser: One codebase for all browsers
  • Mobile emulation: Test on iPhone, Android, etc.
  • Network interception: Mock APIs easily
  • Auto-waiting: No more flaky tests

Installation

Option 1: TypeScript/JavaScript

bash
1# Create new project
2npm init playwright@latest
3
4# Follow the prompts to configure your project

Option 2: Python

bash
1# Install Playwright
2pip install playwright
3
4# Install browsers
5playwright install

That's it! You're ready to start automating.

Your First Test

Let's write a simple test that checks if a website loads correctly.

JavaScript/TypeScript:

javascript
1import { test, expect } from '@playwright/test';
2
3test('homepage loads', async ({ page }) => {
4  // Navigate to website
5  await page.goto('https://example.com');
6  
7  // Check the title
8  await expect(page).toHaveTitle(/Example Domain/);
9  
10  // Verify heading is visible
11  await expect(page.locator('h1')).toBeVisible();
12});

Run it:

bash
1npx playwright test

Python:

python
1from playwright.sync_api import sync_playwright
2
3with sync_playwright() as p:
4    # Launch browser
5    browser = p.chromium.launch(headless=False)
6    page = browser.new_page()
7    
8    # Navigate to website
9    page.goto('https://example.com')
10    
11    # Check title
12    assert 'Example Domain' in page.title()
13    
14    # Check heading is visible
15    assert page.locator('h1').is_visible()
16    
17    browser.close()

Run it:

bash
1python test_example.py

Understanding the Basics

1. Browser, Context, and Page

javascript
1// Browser instance (like opening Chrome)
2const browser = await chromium.launch();
3
4// Browser context (like an incognito window)
5const context = await browser.newContext();
6
7// Page (like a tab)
8const page = await context.newPage();

2. Navigating

javascript
1// Go to URL
2await page.goto('https://example.com');
3
4// Go back
5await page.goBack();
6
7// Go forward
8await page.goForward();
9
10// Reload
11await page.reload();

3. Finding Elements (Locators)

javascript
1// By text
2page.locator('text=Click me');
3
4// By CSS
5page.locator('.button-class');
6
7// By ID
8page.locator('#submit-button');
9
10// By test ID (recommended!)
11page.locator('[data-testid="login-button"]');
12
13// By role
14page.getByRole('button', { name: 'Submit' });

4. Interacting with Elements

javascript
1// Click
2await page.locator('button').click();
3
4// Type text
5await page.locator('#email').fill('user@example.com');
6
7// Select dropdown
8await page.locator('select').selectOption('option1');
9
10// Check checkbox
11await page.locator('#terms').check();
12
13// Upload file
14await page.locator('#file-upload').setInputFiles('document.pdf');

5. Assertions

javascript
1// Check visibility
2await expect(page.locator('.message')).toBeVisible();
3
4// Check text content
5await expect(page.locator('h1')).toHaveText('Welcome');
6
7// Check element count
8await expect(page.locator('.item')).toHaveCount(5);
9
10// Check URL
11await expect(page).toHaveURL(/dashboard/);

Practical Example: Login Test

Let's write a complete login test:

javascript
1import { test, expect } from '@playwright/test';
2
3test('user can login successfully', async ({ page }) => {
4  // 1. Navigate to login page
5  await page.goto('https://example.com/login');
6  
7  // 2. Fill in credentials
8  await page.locator('#email').fill('user@example.com');
9  await page.locator('#password').fill('SecurePassword123');
10  
11  // 3. Click login button
12  await page.locator('button:has-text("Login")').click();
13  
14  // 4. Verify successful login
15  await expect(page).toHaveURL(/.*dashboard/);
16  await expect(page.locator('.welcome-message')).toBeVisible();
17  await expect(page.locator('.username')).toHaveText('user@example.com');
18});
19
20test('shows error for invalid credentials', async ({ page }) => {
21  await page.goto('https://example.com/login');
22  
23  // Try with wrong password
24  await page.locator('#email').fill('user@example.com');
25  await page.locator('#password').fill('WrongPassword');
26  await page.locator('button:has-text("Login")').click();
27  
28  // Verify error message
29  await expect(page.locator('.error-message')).toBeVisible();
30  await expect(page.locator('.error-message')).toHaveText('Invalid credentials');
31});

Running and Debugging Tests

Run Tests

bash
1# Run all tests
2npx playwright test
3
4# Run specific test file
5npx playwright test login.spec.ts
6
7# Run in headed mode (see browser)
8npx playwright test --headed
9
10# Run in debug mode
11npx playwright test --debug

View Test Results

bash
1# Open HTML report
2npx playwright show-report

Common Patterns

Waiting for Elements

javascript
1// Wait for selector
2await page.waitForSelector('.data-loaded');
3
4// Wait for navigation
5await page.waitForURL('**/dashboard');
6
7// Wait for condition
8await page.waitForFunction(() => {
9  return document.querySelectorAll('.item').length > 0;
10});

Taking Screenshots

javascript
1// Full page screenshot
2await page.screenshot({ path: 'screenshot.png', fullPage: true });
3
4// Element screenshot
5await page.locator('.chart').screenshot({ path: 'chart.png' });

Handling Popups

javascript
1// Handle alerts
2page.on('dialog', async dialog => {
3  console.log(dialog.message());
4  await dialog.accept();
5});
6
7// Handle new pages/tabs
8const [newPage] = await Promise.all([
9  context.waitForEvent('page'),
10  page.locator('a[target="_blank"]').click()
11]);
12await newPage.waitForLoadState();

Best Practices for Beginners

1. Use Test IDs

html
1<!-- In your HTML -->
2<button data-testid="submit-btn">Submit</button>
javascript
1// In your test
2await page.locator('[data-testid="submit-btn"]').click();

2. Organize Tests with describe()

javascript
1test.describe('Login Flow', () => {
2  test('successful login', async ({ page }) => {
3    // Test code
4  });
5  
6  test('failed login', async ({ page }) => {
7    // Test code
8  });
9});

3. Use Before/After Hooks

javascript
1test.beforeEach(async ({ page }) => {
2  // Run before each test
3  await page.goto('https://example.com');
4});
5
6test.afterEach(async ({ page }) => {
7  // Cleanup after each test
8  await page.close();
9});

4. Keep Tests Independent

Each test should work on its own:

javascript
1// ❌ Bad: Tests depend on each other
2test('create user', async ({ page }) => {
3  // Creates user...
4});
5
6test('login user', async ({ page }) => {
7  // Assumes user exists from previous test
8});
9
10// ✅ Good: Each test is independent
11test('login user', async ({ page }) => {
12  // Create user in this test
13  // Then test login
14});

Next Steps

Now that you understand the basics:

  1. Practice: Write tests for your own website
  2. Learn Page Object Model: Organize your test code better
  3. Explore CI/CD: Run tests automatically on GitHub Actions
  4. Try Visual Testing: Compare screenshots to detect visual changes
  5. Master Selectors: Learn advanced locator strategies

Common Troubleshooting

Element not found?

  • Make sure the page is fully loaded
  • Check if element is in an iframe
  • Verify your selector is correct

Test is flaky?

  • Use Playwright's auto-waiting (it's built-in!)
  • Avoid using sleep() or wait()
  • Use explicit assertions

Need to see what's happening?

  • Run with --headed flag
  • Use page.pause() to stop and inspect
  • Enable slow motion: { slowMo: 1000 }

Conclusion

Playwright makes browser automation accessible and reliable. With its:

✅ Simple installation ✅ Intuitive API ✅ Excellent documentation ✅ Powerful features

You're ready to start your automation journey. The best way to learn is by doing - so pick a website and start automating!

Happy testing! 🎭✨


Was this helpful?

0

0

0


Comments (0)

Join the Discussion

Sign in to share your thoughts and connect with other readers