0175799004
删除不再需要的文档、测试报告和计划文件,包括标题层级规范、颜色优化报告、测试框架文档等
606 lines
13 KiB
Markdown
606 lines
13 KiB
Markdown
# 测试文档
|
|
|
|
## 测试概述
|
|
|
|
项目使用 Playwright 进行端到端(E2E)测试,测试框架位于 `e2e/` 目录,采用 Page Object 模式组织测试代码。
|
|
|
|
## 测试框架结构
|
|
|
|
```
|
|
e2e/
|
|
├── src/
|
|
│ ├── config/ # 配置文件
|
|
│ │ ├── environments.ts # 环境配置
|
|
│ │ └── network-configs.ts # 网络配置
|
|
│ ├── data/ # 测试数据
|
|
│ │ └── test-data.ts
|
|
│ ├── fixtures/ # 测试 Fixtures
|
|
│ │ ├── base.fixture.ts # 基础 Fixture
|
|
│ │ └── a11y.fixture.ts # 可访问性 Fixture
|
|
│ ├── pages/ # Page Object Model
|
|
│ │ ├── BasePage.ts # 基础页面
|
|
│ │ ├── HomePage.ts # 首页
|
|
│ │ ├── AboutPage.ts # 关于页
|
|
│ │ ├── CasesPage.ts # 案例页
|
|
│ │ ├── ContactPage.ts # 联系页
|
|
│ │ ├── NewsPage.ts # 新闻页
|
|
│ │ ├── ProductsPage.ts # 产品页
|
|
│ │ ├── ServicesPage.ts # 服务页
|
|
│ │ └── SolutionsPage.ts # 解决方案页
|
|
│ └── tests/ # 测试用例
|
|
│ ├── accessibility/ # 可访问性测试
|
|
│ ├── debug/ # 调试测试
|
|
│ ├── deployment/ # 部署就绪测试
|
|
│ ├── error-handling/ # 错误处理测试
|
|
│ ├── mobile/ # 移动端测试
|
|
│ ├── performance/ # 性能测试
|
|
│ ├── regression/ # 回归测试
|
|
│ ├── responsive/ # 响应式测试
|
|
│ ├── security/ # 安全测试
|
|
│ ├── smoke/ # 冒烟测试
|
|
│ ├── utils/ # 工具测试
|
|
│ └── visual/ # 视觉回归测试
|
|
├── playwright.config.ts # Playwright 配置
|
|
├── package.json
|
|
└── .env.example
|
|
```
|
|
|
|
## 测试类型
|
|
|
|
### 1. 冒烟测试 (Smoke Tests)
|
|
|
|
**目录**: `e2e/src/tests/smoke/`
|
|
|
|
**目的**: 验证核心功能是否正常工作
|
|
|
|
**测试文件**:
|
|
- `all-pages.spec.ts` - 所有页面加载测试
|
|
- `home-page.smoke.spec.ts` - 首页冒烟测试
|
|
- `contact-page.smoke.spec.ts` - 联系页冒烟测试
|
|
- `navigation.smoke.spec.ts` - 导航冒烟测试
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:smoke
|
|
# 或
|
|
npx playwright test --grep @smoke
|
|
```
|
|
|
|
### 2. 回归测试 (Regression Tests)
|
|
|
|
**目录**: `e2e/src/tests/regression/`
|
|
|
|
**目的**: 确保新代码没有破坏现有功能
|
|
|
|
**测试文件**:
|
|
- `contact-form.regression.spec.ts` - 联系表单回归测试
|
|
- `home-page.regression.spec.ts` - 首页回归测试
|
|
- `navigation.spec.ts` - 导航回归测试
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:regression
|
|
# 或
|
|
npx playwright test --grep @regression
|
|
```
|
|
|
|
### 3. 性能测试 (Performance Tests)
|
|
|
|
**目录**: `e2e/src/tests/performance/`
|
|
|
|
**目的**: 验证页面性能指标
|
|
|
|
**测试文件**:
|
|
- `core-web-vitals.spec.ts` - Core Web Vitals 测试
|
|
- `performance.spec.ts` - 通用性能测试
|
|
- `image-loading.spec.ts` - 图片加载性能
|
|
- `interaction-performance.spec.ts` - 交互性能测试
|
|
|
|
**监控指标**:
|
|
- LCP (Largest Contentful Paint) < 2.5s
|
|
- FID (First Input Delay) < 100ms
|
|
- CLS (Cumulative Layout Shift) < 0.1
|
|
- TTFB (Time to First Byte) < 600ms
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:performance
|
|
# 或
|
|
npx playwright test --grep @performance
|
|
```
|
|
|
|
### 4. 响应式测试 (Responsive Tests)
|
|
|
|
**目录**: `e2e/src/tests/responsive/`
|
|
|
|
**目的**: 验证多设备适配
|
|
|
|
**测试文件**:
|
|
- `responsive.spec.ts` - 响应式布局测试
|
|
- `mobile-interaction.spec.ts` - 移动端交互测试
|
|
|
|
**测试设备**:
|
|
- Desktop: 1920x1080, 1366x768
|
|
- Tablet: iPad Pro (1024x1366), iPad Air (820x1180)
|
|
- Mobile: iPhone 12 (390x844), iPhone SE (375x667), Pixel 5 (393x851)
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:responsive
|
|
# 或
|
|
npx playwright test --grep @responsive
|
|
```
|
|
|
|
### 5. 可访问性测试 (Accessibility Tests)
|
|
|
|
**目录**: `e2e/src/tests/accessibility/`
|
|
|
|
**目的**: 验证 WCAG 合规性
|
|
|
|
**测试文件**:
|
|
- `accessibility.spec.ts` - 可访问性测试
|
|
- `wcag-compliance.spec.ts` - WCAG 合规测试
|
|
|
|
**检查项**:
|
|
- 颜色对比度 ≥ 4.5:1 (AA 级别)
|
|
- 键盘导航支持
|
|
- 屏幕阅读器兼容
|
|
- ARIA 属性正确性
|
|
- 焦点顺序合理
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:accessibility
|
|
# 或
|
|
npx playwright test --grep @accessibility
|
|
```
|
|
|
|
### 6. 安全测试 (Security Tests)
|
|
|
|
**目录**: `e2e/src/tests/security/`
|
|
|
|
**目的**: 验证安全防护措施
|
|
|
|
**测试文件**:
|
|
- `security.spec.ts` - 通用安全测试
|
|
- `xss-protection.spec.ts` - XSS 防护测试
|
|
- `csrf-protection.spec.ts` - CSRF 防护测试
|
|
|
|
**检查项**:
|
|
- XSS 攻击防护
|
|
- CSRF Token 验证
|
|
- 安全头部配置
|
|
- 表单验证
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:security
|
|
# 或
|
|
npx playwright test --grep @security
|
|
```
|
|
|
|
### 7. 视觉回归测试 (Visual Tests)
|
|
|
|
**目录**: `e2e/src/tests/visual/`
|
|
|
|
**目的**: 检测 UI 变化
|
|
|
|
**测试文件**:
|
|
- `home-page.visual.spec.ts` - 首页视觉测试
|
|
- `contact-page.visual.spec.ts` - 联系页视觉测试
|
|
- `visual-regression.spec.ts` - 视觉回归测试
|
|
|
|
**快照目录**:
|
|
- `*-snapshots/` - 基线快照
|
|
|
|
**运行命令**:
|
|
```bash
|
|
npm run test:visual
|
|
# 或
|
|
npx playwright test --grep @visual
|
|
```
|
|
|
|
**更新快照**:
|
|
```bash
|
|
npx playwright test --grep @visual --update-snapshots
|
|
```
|
|
|
|
### 8. 移动端测试 (Mobile Tests)
|
|
|
|
**目录**: `e2e/src/tests/mobile/`
|
|
|
|
**目的**: 验证移动端功能
|
|
|
|
**测试文件**:
|
|
- `compatibility/mobile-compatibility.spec.ts` - 兼容性测试
|
|
- `gesture/mobile-gesture.spec.ts` - 手势测试
|
|
- `network/network-environment.spec.ts` - 网络环境测试
|
|
- `performance/mobile-performance.spec.ts` - 移动性能测试
|
|
- `pwa/pwa-functionality.spec.ts` - PWA 功能测试
|
|
- `mobile-ux.spec.ts` - 移动端 UX 测试
|
|
|
|
### 9. 部署就绪测试 (Deployment Tests)
|
|
|
|
**目录**: `e2e/src/tests/deployment/`
|
|
|
|
**目的**: 验证部署前检查
|
|
|
|
**测试文件**:
|
|
- `deployment-readiness.spec.ts` - 部署就绪检查
|
|
- `quick-check.spec.ts` - 快速检查
|
|
|
|
## Page Object Model
|
|
|
|
### 基础页面类
|
|
|
|
```typescript
|
|
// e2e/src/pages/BasePage.ts
|
|
export class BasePage {
|
|
readonly page: Page;
|
|
|
|
constructor(page: Page) {
|
|
this.page = page;
|
|
}
|
|
|
|
async navigate(path: string) {
|
|
await this.page.goto(path);
|
|
}
|
|
|
|
async waitForPageLoad() {
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
async takeScreenshot(name: string) {
|
|
await this.page.screenshot({ path: `screenshots/${name}.png` });
|
|
}
|
|
}
|
|
```
|
|
|
|
### 首页 Page Object
|
|
|
|
```typescript
|
|
// e2e/src/pages/HomePage.ts
|
|
import { BasePage } from './BasePage';
|
|
|
|
export class HomePage extends BasePage {
|
|
readonly heroSection: Locator;
|
|
readonly servicesSection: Locator;
|
|
readonly productsSection: Locator;
|
|
|
|
constructor(page: Page) {
|
|
super(page);
|
|
this.heroSection = page.locator('[data-testid="hero-section"]');
|
|
this.servicesSection = page.locator('#services');
|
|
this.productsSection = page.locator('#products');
|
|
}
|
|
|
|
async goto() {
|
|
await this.navigate('/');
|
|
await this.waitForPageLoad();
|
|
}
|
|
|
|
async scrollToSection(sectionId: string) {
|
|
await this.page.locator(`#${sectionId}`).scrollIntoViewIfNeeded();
|
|
}
|
|
}
|
|
```
|
|
|
|
### 使用示例
|
|
|
|
```typescript
|
|
// e2e/src/tests/smoke/home-page.smoke.spec.ts
|
|
import { test, expect } from '@playwright/test';
|
|
import { HomePage } from '../../pages/HomePage';
|
|
|
|
test.describe('首页冒烟测试', () => {
|
|
let homePage: HomePage;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
homePage = new HomePage(page);
|
|
await homePage.goto();
|
|
});
|
|
|
|
test('首页加载成功', async () => {
|
|
await expect(homePage.heroSection).toBeVisible();
|
|
});
|
|
});
|
|
```
|
|
|
|
## 测试配置
|
|
|
|
### Playwright 配置
|
|
|
|
```typescript
|
|
// e2e/playwright.config.ts
|
|
export default defineConfig({
|
|
testDir: './src/tests',
|
|
fullyParallel: true,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: process.env.CI ? 2 : 0,
|
|
workers: process.env.CI ? 4 : '50%',
|
|
reporter: [
|
|
['html'],
|
|
['json', { outputFile: 'test-results/results.json' }],
|
|
['junit', { outputFile: 'test-results/junit.xml' }],
|
|
['allure-playwright'],
|
|
],
|
|
timeout: 90000,
|
|
use: {
|
|
baseURL: 'http://localhost:3000',
|
|
trace: 'on-first-retry',
|
|
screenshot: 'only-on-failure',
|
|
video: 'on-first-retry',
|
|
headless: true,
|
|
},
|
|
projects: [
|
|
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
|
|
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
|
|
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
|
|
{ name: 'Mobile Safari', use: { ...devices['iPhone 12'] } },
|
|
],
|
|
webServer: {
|
|
command: 'cd .. && npm run dev',
|
|
url: 'http://localhost:3000',
|
|
reuseExistingServer: !process.env.CI,
|
|
},
|
|
});
|
|
```
|
|
|
|
### 环境配置
|
|
|
|
```typescript
|
|
// e2e/src/config/environments.ts
|
|
export interface Environment {
|
|
name: string;
|
|
baseURL: string;
|
|
retries: number;
|
|
trace: 'on' | 'off' | 'on-first-retry';
|
|
screenshot: 'on' | 'off' | 'only-on-failure';
|
|
video: 'on' | 'off' | 'on-first-retry';
|
|
headless: boolean;
|
|
slowMo: number;
|
|
}
|
|
|
|
export const environments: Record<string, Environment> = {
|
|
development: {
|
|
name: 'development',
|
|
baseURL: 'http://localhost:3000',
|
|
retries: 0,
|
|
trace: 'on-first-retry',
|
|
screenshot: 'only-on-failure',
|
|
video: 'on-first-retry',
|
|
headless: true,
|
|
slowMo: 0,
|
|
},
|
|
production: {
|
|
name: 'production',
|
|
baseURL: 'https://www.novalon.cn',
|
|
retries: 2,
|
|
trace: 'on-first-retry',
|
|
screenshot: 'only-on-failure',
|
|
video: 'on-first-retry',
|
|
headless: true,
|
|
slowMo: 0,
|
|
},
|
|
};
|
|
|
|
export function getEnvironment(): Environment {
|
|
const env = process.env.TEST_ENV || 'development';
|
|
return environments[env];
|
|
}
|
|
```
|
|
|
|
## 运行测试
|
|
|
|
### 本地运行
|
|
|
|
```bash
|
|
# 进入测试目录
|
|
cd e2e
|
|
|
|
# 安装依赖
|
|
npm install
|
|
|
|
# 安装浏览器
|
|
npx playwright install
|
|
|
|
# 运行所有测试
|
|
npm run test
|
|
|
|
# 运行特定测试
|
|
npx playwright test path/to/test.spec.ts
|
|
|
|
# 运行带标签的测试
|
|
npx playwright test --grep @smoke
|
|
|
|
# UI 模式
|
|
npm run test:ui
|
|
|
|
# 调试模式
|
|
npm run test:debug
|
|
|
|
# 有头模式
|
|
npm run test:headed
|
|
```
|
|
|
|
### CI 环境运行
|
|
|
|
```bash
|
|
# CI 模式(禁止 only、增加重试)
|
|
CI=true npx playwright test
|
|
```
|
|
|
|
## 测试报告
|
|
|
|
### HTML 报告
|
|
|
|
```bash
|
|
npx playwright show-report
|
|
```
|
|
|
|
### Allure 报告
|
|
|
|
```bash
|
|
# 生成报告
|
|
npm run test:allure
|
|
|
|
# 打开报告
|
|
npm run test:allure:open
|
|
|
|
# 实时服务
|
|
npm run test:allure:serve
|
|
```
|
|
|
|
### JUnit 报告
|
|
|
|
用于 CI 集成,输出到 `test-results/junit.xml`。
|
|
|
|
## 测试最佳实践
|
|
|
|
### 1. 使用数据测试 ID
|
|
|
|
```tsx
|
|
// 组件中
|
|
<div data-testid="hero-section">
|
|
|
|
// 测试中
|
|
await page.locator('[data-testid="hero-section"]')
|
|
```
|
|
|
|
### 2. 等待策略
|
|
|
|
```typescript
|
|
// 等待元素可见
|
|
await expect(locator).toBeVisible();
|
|
|
|
// 等待网络空闲
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// 等待特定响应
|
|
await page.waitForResponse('**/api/contact');
|
|
```
|
|
|
|
### 3. 避免硬编码等待
|
|
|
|
```typescript
|
|
// 不推荐
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 推荐
|
|
await expect(locator).toBeVisible();
|
|
```
|
|
|
|
### 4. 使用 Fixtures
|
|
|
|
```typescript
|
|
// e2e/src/fixtures/base.fixture.ts
|
|
import { test as base } from '@playwright/test';
|
|
import { HomePage } from '../pages/HomePage';
|
|
|
|
export const test = base.extend<{
|
|
homePage: HomePage;
|
|
}>({
|
|
homePage: async ({ page }, use) => {
|
|
const homePage = new HomePage(page);
|
|
await use(homePage);
|
|
},
|
|
});
|
|
```
|
|
|
|
### 5. 测试隔离
|
|
|
|
```typescript
|
|
test.describe('测试组', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// 每个测试前的初始化
|
|
});
|
|
|
|
test.afterEach(async ({ page }) => {
|
|
// 每个测试后的清理
|
|
});
|
|
});
|
|
```
|
|
|
|
## CI 集成
|
|
|
|
### Woodpecker CI 配置
|
|
|
|
```yaml
|
|
# .woodpecker.yml
|
|
pipeline:
|
|
e2e-tests:
|
|
image: node:18-alpine
|
|
environment:
|
|
NODE_ENV: test
|
|
CI: true
|
|
commands:
|
|
- cd e2e
|
|
- npm ci
|
|
- npx playwright install --with-deps chromium
|
|
- npm run test:ci
|
|
when:
|
|
event:
|
|
- push
|
|
- pull_request
|
|
```
|
|
|
|
### 测试命令
|
|
|
|
```json
|
|
{
|
|
"scripts": {
|
|
"test": "playwright test",
|
|
"test:smoke": "playwright test --grep @smoke",
|
|
"test:regression": "playwright test --grep @regression",
|
|
"test:performance": "playwright test --grep @performance",
|
|
"test:responsive": "playwright test --grep @responsive",
|
|
"test:visual": "playwright test --grep @visual",
|
|
"test:accessibility": "playwright test --grep @accessibility",
|
|
"test:security": "playwright test --grep @security",
|
|
"test:ci": "playwright test --reporter=html,json,junit"
|
|
}
|
|
}
|
|
```
|
|
|
|
## 调试技巧
|
|
|
|
### 1. Trace Viewer
|
|
|
|
```bash
|
|
# 运行测试并生成 trace
|
|
npx playwright test --trace on
|
|
|
|
# 查看 trace
|
|
npx playwright show-trace trace.zip
|
|
```
|
|
|
|
### 2. 截图和视频
|
|
|
|
```typescript
|
|
// 手动截图
|
|
await page.screenshot({ path: 'debug.png' });
|
|
|
|
// 元素截图
|
|
await locator.screenshot({ path: 'element.png' });
|
|
|
|
// 全页截图
|
|
await page.screenshot({ path: 'full.png', fullPage: true });
|
|
```
|
|
|
|
### 3. 控制台日志
|
|
|
|
```typescript
|
|
// 监听控制台
|
|
page.on('console', msg => console.log(msg.text()));
|
|
|
|
// 监听页面错误
|
|
page.on('pageerror', error => console.error(error));
|
|
```
|
|
|
|
### 4. Playwright Inspector
|
|
|
|
```bash
|
|
npx playwright test --debug
|
|
```
|