Playwright 脚本

基础导航与交互

import { test, expect } from '@playwright/test'; test('登录流程', async ({ page }) => { await page.goto('https://example.com/login'); await page.goto('https://example.com', { waitUntil: 'networkidle' }); await page.fill('#email', 'user@example.com'); await page.fill('[name="password"]', 'secret123'); await page.selectOption('select#role', 'admin'); await page.check('#rememberMe'); await page.click('button[type="submit"]'); await page.keyboard.press('Enter'); });

选择器

// CSS 选择器 page.locator('#submit-btn'); page.locator('input[type="email"]'); // ARIA 角色(推荐) page.getByRole('button', { name: '提交' }); page.getByRole('textbox', { name: '邮箱' }); page.getByLabel('密码'); page.getByTestId('submit-button'); // 链式过滤 page.locator('.card').filter({ hasText: '张三' }); page.locator('li').nth(2);

等待策略

// 自动等待 — 大多数操作自动等待元素可用 await page.click('#submit'); await page.waitForSelector('.modal', { state: 'visible' }); await page.waitForURL('**/dashboard'); await page.waitForLoadState('networkidle'); // expect 自动等待 await expect(page.locator('.success')).toBeVisible({ timeout: 5000 }); await expect(page.locator('#count')).toHaveText('3');

截图与录制视频

// 手动截图 await page.screenshot({ path: 'screenshot.png' }); await page.screenshot({ path: 'full.png', fullPage: true }); // playwright.config.ts — 失败时自动保留 export default { use: { screenshot: 'only-on-failure', video: 'retain-on-failure', trace: 'on-first-retry', }, }; // 查看追踪文件 // npx playwright show-trace trace.zip

测试 Fixtures

import { test as base } from '@playwright/test'; export const test = base.extend({ loggedInPage: async ({ page }, use) => { await page.goto('/login'); await page.fill('#email', 'user@example.com'); await page.fill('#password', 'testpass'); await page.click('[type="submit"]'); await page.waitForURL('**/dashboard'); await use(page); }, }); // 使用 test('管理员查看用户', async ({ loggedInPage }) => { await loggedInPage.goto('/admin/users'); await expect(loggedInPage.getByRole('table')).toBeVisible(); });

playwright.config.ts 概览

import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './tests', timeout: 30_000, retries: process.env.CI ? 2 : 0, use: { baseURL: 'http://localhost:3000', screenshot: 'only-on-failure', video: 'retain-on-failure', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, { name: 'mobile', use: { ...devices['iPhone 13'] } }, ], });