Playwright Testing Guide: Writing, Running, and Optimizing Automated Tests
Last updated on: February 25, 2025
Notesly Team
School Student
Share :
1. Introduction
Overview of Automated Testing and Playwright’s Role
- Automated Testing:
- The practice of using scripts to execute tests automatically, replacing repetitive manual checks. Ensures faster feedback, consistency, and scalability.
- Playwright’s Role:
- A modern framework for end-to-end testing of web apps. Supports multiple browsers (Chromium, Firefox, WebKit), languages (JavaScript, Python, .NET), and platforms.
Key Concepts
- Test Scripts: Code that automates user interactions (e.g., clicking buttons).
- Actions: Simulated user behaviors (e.g.,
click()
,type()
). - Assertions: Validations to check outcomes (e.g.,
expect(page).toHaveTitle(...)
). - Test Isolation: Ensuring tests run independently to prevent interference.
2. Writing Your First Test
Setting Up a Basic Test File
- Create a test file (e.g.,
example.spec.ts
). - Import Playwright:
import { test, expect } from '@playwright/test';
- Write a test block:
test('My first test', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle('Example Domain');
});
Anatomy of a Playwright Test
- Test Block:
test('description', callback)
defines a test case. - Descriptions: Use clear names like
'Verify login functionality'
.
Running the Test and Interpreting Results
- Run tests:
npx playwright test
3. Working with Actions and Interactions
Actions Overview
- Common Actions:
await page.click('#submit-button'); // Click
await page.fill('#email', 'user@test.com'); // Type text
await page.hover('.menu-item'); // Hover
Navigation
- Navigate to a URL:
await page.goto('https://example.com/login');
- Reload:
await page.reload();
- Handle Redirects: Playwright automatically follows redirects.
Interactions
- Forms:
await page.selectOption('#country', 'India'); // Dropdown
await page.check('#terms-checkbox'); // Checkbox
- Dynamic Elements:
- Use
page.waitForSelector()
to handle elements that load asynchronously.
Basic Actions
- Keyboard Shortcuts:
await page.keyboard.press('Enter');
- File Uploads:
await page.setInputFiles('#file-upload', 'path/to/file.pdf');
- Drag-and-Drop:
await page.dragAndDrop('#source-element', '#target-element');
4. Assertions in Playwright
Validating Outcomes with expect
- Common Assertions:
await expect(page).toHaveTitle('Dashboard');
await expect(page.locator('.status')).toHaveText('Success');
await expect(page).toHaveURL(/\/dashboard/); // Regex match
Custom Assertions and Retry Logic
- Retry Logic:
await expect(async () => {
expect(await page.innerText('.status')).toBe('Loaded');
}).toPass({ timeout: 5000 }); // Retry for 5 seconds
- Soft Assertions:
expect.soft(await page.textContent('#error')).toBeNull(); // Continue on failure
5. Test Isolation
Importance of Isolated Tests
- Prevents flaky tests caused by shared state.
- Ensures reliability in parallel execution.
Playwright’s Built-In Isolation
- Each test runs in a new browser context (separate cookies, storage).
- Configured via
test.use()
:
test.use({ storageState: 'admin-auth.json' }); // Isolated auth state
Avoiding State Leakage
- Never use global variables to store test data.
- Reset databases or APIs before/after tests if needed.
6. Using Test Hooks
Setup and Teardown Workflows
- Global Setup (Once per Test Suite):
test.beforeAll(async () => {
await startMockServer(); // Start a server
});
- Per-Test Setup (Before Each Test):
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await page.fill('#username', 'testuser');
await page.click('#login');
});
Sharing Context Between Tests
- Use fixtures to share resources (e.g., authenticated sessions).
Best Practices for Reusable Configurations
- Centralize common setups in a
base-test.ts
file. - Use
test.describe()
to group tests with shared hooks.
7. Conclusion
Recap of Core Concepts
- Playwright simplifies testing with cross-browser support and intuitive APIs.
- Key skills: writing actions, assertions, and isolated tests.
Addinational
- Scaling Tests: Parallel execution, sharding.
- CI/CD Integration: Run tests in GitHub Actions, Jenkins.
- Advanced Features: API testing, visual regression, mobile emulation.
