Browser-based UI testing and E2E automation.
✅ USE this skill when:
❌ DON'T use this skill when:
api-tester# Navigate and screenshot
npx -y playwright@latest test --browser=chromium -g "test name"
# Or write inline script
node -e "
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log('Title:', await page.title());
await page.screenshot({ path: '/tmp/screenshot.png' });
await browser.close();
})();
"
When user provides a page URL and test scenario, generate:
// tests/example.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Login Page Tests', () => {
test('TC001: Successful login', async ({ page }) => {
await page.goto('https://app.example.com/login');
// Fill form
await page.fill('input[name="username"]', 'admin');
await page.fill('input[name="password"]', 'Admin@123');
await page.click('button[type="submit"]');
// Verify redirect
await expect(page).toHaveURL(/dashboard/);
await expect(page.locator('h1')).toContainText('Welcome');
});
test('TC002: Login with empty fields', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.click('button[type="submit"]');
// Verify validation messages
await expect(page.locator('.error-message')).toBeVisible();
});
test('TC003: Login with wrong password', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('input[name="username"]', 'admin');
await page.fill('input[name="password"]', 'wrongpass');
await page.click('button[type="submit"]');
await expect(page.locator('.error-alert')).toContainText('Invalid');
});
});
Run tests:
# Install Playwright browsers (first time)
npx playwright install chromium
# Run tests
npx playwright test tests/example.spec.js --reporter=list
# Run with headed browser (visible)
npx playwright test --headed
# Run specific test
npx playwright test -g "TC001"
# Generate HTML report
npx playwright test --reporter=html
npx playwright show-report
data-testid attribute (most stable)role + accessible nameplaceholder / label text// Preferred
page.getByTestId('submit-btn')
page.getByRole('button', { name: 'Submit' })
page.getByPlaceholder('Enter email')
page.getByLabel('Username')
// Fallback
page.locator('button.submit-btn')
page.locator('//button[contains(text(),"Submit")]')
// Wait for element
await page.waitForSelector('.result-list');
// Wait for navigation
await page.waitForURL('**/dashboard');
// Wait for network idle
await page.waitForLoadState('networkidle');
// Wait for specific response
const response = await page.waitForResponse('**/api/users');
// Full page screenshot
await page.screenshot({ path: 'full-page.png', fullPage: true });
// Element screenshot
await page.locator('.chart').screenshot({ path: 'chart.png' });
// Visual comparison (Playwright built-in)
await expect(page).toHaveScreenshot('homepage.png');
For any web page, consider testing:
| Category | Test Points |
|---|---|
| ---------- | ------------- |
| Navigation | Links work, breadcrumbs correct, back button, deep links |
| Forms | Required fields, validation messages, submit, reset |
| Auth | Login, logout, session expiry, role-based access |
| Responsive | Mobile viewport, tablet, desktop breakpoints |
| Accessibility | Tab order, screen reader, color contrast, ARIA |
| Error States | 404 page, network error, empty state, timeout |
| Data Display | Pagination, sorting, filtering, search |
| File Operations | Upload, download, preview |
// Install axe-core for a11y testing
// npm install @axe-core/playwright
const { test, expect } = require('@playwright/test');
const AxeBuilder = require('@axe-core/playwright').default;
test('accessibility scan', async ({ page }) => {
await page.goto('https://example.com');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
headless: true in CI environmentspage.waitForLoadState('networkidle') before assertionsWhen Playwright is not available or user prefers Selenium:
"""Selenium E2E Test Example"""
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
@pytest.fixture
def driver():
opts = Options()
opts.add_argument('--headless')
opts.add_argument('--no-sandbox')
opts.add_argument('--disable-dev-shm-usage')
d = webdriver.Chrome(options=opts)
d.implicitly_wait(10)
yield d
d.quit()
class TestLogin:
def test_successful_login(self, driver):
driver.get('https://app.example.com/login')
driver.find_element(By.NAME, 'username').send_keys('admin')
driver.find_element(By.NAME, 'password').send_keys('Admin@123')
driver.find_element(By.CSS_SELECTOR, 'button[type=submit]').click()
WebDriverWait(driver, 10).until(
EC.url_contains('/dashboard')
)
assert 'dashboard' in driver.current_url
def test_screenshot_on_failure(self, driver):
driver.get('https://app.example.com/broken-page')
driver.save_screenshot('/tmp/failure.png')
Install: pip install selenium webdriver-manager
| 维度 | Playwright | Selenium |
|---|---|---|
| ------ | ----------- | ---------- |
| 安装 | npx playwright install 一键搞定 | 需要 WebDriver + 浏览器匹配 |
| 速度 | 更快(原生 CDP/WebSocket) | 较慢(HTTP 协议通信) |
| 自动等待 | 内置智能等待 | 需手动写 WebDriverWait |
| 多浏览器 | Chromium/Firefox/WebKit | Chrome/Firefox/Edge/Safari |
| 语言 | JS/TS/Python/Java/.NET | Python/Java/C#/Ruby/JS |
| 适合 | 新项目、快速验证、CI | 已有 Selenium 框架的团队 |
建议: 新项目优先 Playwright,已有 Selenium 资产的项目继续用 Selenium。
共 1 个版本