Getting Started with Playwright Automation: A Beginner's Guide
November 22, 2024
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
bash1# Create new project 2npm init playwright@latest 3 4# Follow the prompts to configure your project
Option 2: Python
bash1# 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:
javascript1import { 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:
bash1npx playwright test
Python:
python1from 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:
bash1python test_example.py
Understanding the Basics
1. Browser, Context, and Page
javascript1// 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
javascript1// 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)
javascript1// 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
javascript1// 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
javascript1// 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:
javascript1import { 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
bash1# 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
bash1# Open HTML report 2npx playwright show-report
Common Patterns
Waiting for Elements
javascript1// 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
javascript1// 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
javascript1// 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
html1<!-- In your HTML --> 2<button data-testid="submit-btn">Submit</button>
javascript1// In your test 2await page.locator('[data-testid="submit-btn"]').click();
2. Organize Tests with describe()
javascript1test.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
javascript1test.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:
javascript1// ❌ 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:
- Practice: Write tests for your own website
- Learn Page Object Model: Organize your test code better
- Explore CI/CD: Run tests automatically on GitHub Actions
- Try Visual Testing: Compare screenshots to detect visual changes
- 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()orwait() - Use explicit assertions
Need to see what's happening?
- Run with
--headedflag - 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
Related Articles
Playwright Automation with TypeScript: A Modern Approach
Discover how to build robust end-to-end test automation using Playwright and TypeScript. Learn best practices, type safety benefits, and real-world implementation strategies.
Playwright Automation with Python: Simplicity Meets Power
Learn how to leverage Playwright with Python for efficient browser automation. Discover Pythonic patterns, async/await usage, and practical testing strategies.
AI Agents for Automation: The Future of Intelligent Testing
Explore how AI-powered agents are revolutionizing test automation. Learn about autonomous testing agents, self-healing tests, and the next generation of intelligent automation tools.