Update from Sync Service
This commit is contained in:
192
AI工程/概念/Playwright.md
Executable file
192
AI工程/概念/Playwright.md
Executable file
@@ -0,0 +1,192 @@
|
||||
# Playwright
|
||||
|
||||
> 相关:[[测试策略金字塔]]、[[Browser_Use]]、[[MCP]]
|
||||
|
||||
## 定义
|
||||
|
||||
**Playwright**是最流行的浏览器自动化测试框架,支持Chromium、Firefox、WebKit。
|
||||
|
||||
**核心思想**:提供稳定、快速的浏览器自动化能力,支持多浏览器、多平台。
|
||||
|
||||
## 核心特征
|
||||
|
||||
### 1. 多浏览器支持
|
||||
- Chromium(Chrome、Edge)
|
||||
- Firefox
|
||||
- WebKit(Safari)
|
||||
- 一套API,多浏览器运行
|
||||
|
||||
### 2. 自动化能力
|
||||
- 自动等待元素可操作
|
||||
- 自动重试断言
|
||||
- 网络拦截
|
||||
- 截图和视频录制
|
||||
|
||||
### 3. 稳定性
|
||||
- 使用稳定的选择器
|
||||
- 自动处理动态内容
|
||||
- 支持并行测试
|
||||
|
||||
## 基本使用
|
||||
|
||||
### 安装
|
||||
```bash
|
||||
npm init playwright@latest
|
||||
```
|
||||
|
||||
### 基本测试
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
await page.getByText('Get Started').click();
|
||||
await expect(page).toHaveTitle(/Getting started/);
|
||||
});
|
||||
```
|
||||
|
||||
### 登录测试
|
||||
```typescript
|
||||
test('login success', async ({ page }) => {
|
||||
await page.goto('https://example.com/login');
|
||||
await page.getByPlaceholder('Email').fill('test@example.com');
|
||||
await page.getByPlaceholder('Password').fill('123456');
|
||||
await page.getByRole('button', { name: 'Login' }).click();
|
||||
await expect(page).toHaveURL(/dashboard/);
|
||||
await expect(page.getByText('Welcome')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
### API登录(更稳定)
|
||||
```typescript
|
||||
test('login via API + set session', async ({ page, request }) => {
|
||||
const response = await request.post('https://example.com/api/login', {
|
||||
data: {
|
||||
email: 'test@example.com',
|
||||
password: '123456'
|
||||
}
|
||||
});
|
||||
|
||||
expect(response.ok()).toBeTruthy();
|
||||
|
||||
const cookies = await response.headers()['set-cookie'];
|
||||
|
||||
await page.context().addCookies([{
|
||||
name: 'session',
|
||||
value: cookies,
|
||||
domain: 'example.com',
|
||||
path: '/'
|
||||
}]);
|
||||
|
||||
await page.goto('https://example.com/dashboard');
|
||||
await expect(page.getByText('Welcome')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
## 选择器最佳实践
|
||||
|
||||
### 推荐的选择器(从优到差)
|
||||
```typescript
|
||||
// 1. 使用data-testid(最稳定)
|
||||
await page.getByTestId('submit-button').click();
|
||||
|
||||
// 2. 使用角色和名称(推荐)
|
||||
await page.getByRole('button', { name: 'Login' }).click();
|
||||
|
||||
// 3. 使用标签文本(推荐)
|
||||
await page.getByLabel('Email').fill('test@example.com');
|
||||
|
||||
// 4. 使用占位符(可用)
|
||||
await page.getByPlaceholder('Enter your email').fill('test@example.com');
|
||||
|
||||
// 5. 使用文本(可用)
|
||||
await page.getByText('Welcome').toBeVisible();
|
||||
|
||||
// 6. 使用CSS选择器(不推荐,容易变)
|
||||
await page.locator('.btn-primary').click();
|
||||
|
||||
// 7. 使用XPath(不推荐,容易变)
|
||||
await page.locator('//button[@type="submit"]').click();
|
||||
```
|
||||
|
||||
## 等待策略
|
||||
|
||||
### 自动等待
|
||||
```typescript
|
||||
// Playwright自动等待元素可见、可操作
|
||||
await page.getByRole('button', { name: 'Login' }).click();
|
||||
```
|
||||
|
||||
### 显式等待
|
||||
```typescript
|
||||
// 等待URL变化
|
||||
await expect(page).toHaveURL(/dashboard/);
|
||||
|
||||
// 等待元素可见
|
||||
await expect(page.getByText('Welcome')).toBeVisible();
|
||||
|
||||
// 等待元素隐藏
|
||||
await expect(page.getByText('Loading')).toBeHidden();
|
||||
|
||||
// 等待网络请求完成
|
||||
await page.waitForLoadState('networkidle');
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
### playwright.config.ts
|
||||
```typescript
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: 'html',
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000',
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
projects: [
|
||||
{ name: 'chromium', use: { browserName: 'chromium' } },
|
||||
{ name: 'firefox', use: { browserName: 'firefox' } },
|
||||
{ name: 'webkit', use: { browserName: 'webkit' } },
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 适用场景
|
||||
|
||||
- **E2E测试**:最流行的E2E测试框架
|
||||
- **浏览器自动化**:自动化浏览器操作
|
||||
- **视觉回归测试**:截图对比
|
||||
- **性能测试**:页面加载性能
|
||||
|
||||
## 优势
|
||||
|
||||
- **多浏览器支持**:一套API,多浏览器运行
|
||||
- **稳定性**:自动等待、自动重试
|
||||
- **速度快**:比Selenium快
|
||||
- **生态成熟**:社区活跃,文档完善
|
||||
|
||||
## 挑战
|
||||
|
||||
- **学习成本**:需要了解框架API
|
||||
- **维护成本**:需要维护测试脚本
|
||||
- **运行时间**:完整的E2E测试运行时间长
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **优先使用稳定的选择器**:data-testid、角色、标签
|
||||
2. **使用API登录**:提高测试速度
|
||||
3. **测试数据管理**:使用Fixture或API准备数据
|
||||
4. **并行测试**:提高测试效率
|
||||
5. **CI/CD集成**:每次提交自动运行测试
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[测试策略金字塔]]:Playwright是E2E测试的工具
|
||||
- [[Browser_Use]]:Playwright和Browser Use的对比
|
||||
- [[MCP]]:Playwright MCP是MCP的一种实现
|
||||
Reference in New Issue
Block a user