feat: 配置多环境支持
- 创建环境配置文件environments.ts - 支持development/staging/production三个环境 - 更新playwright.config.ts使用环境配置 - 创建.env.example环境变量示例 - 创建ENVIRONMENT.md环境配置指南 - 支持CI/CD集成配置
This commit is contained in:
+28
-1
@@ -1,2 +1,29 @@
|
|||||||
BASE_URL=http://localhost:3000
|
# 测试环境配置
|
||||||
|
# 可选值: development, staging, production
|
||||||
|
TEST_ENV=development
|
||||||
|
|
||||||
|
# 基础URL(可选,会覆盖环境配置)
|
||||||
|
# BASE_URL=http://localhost:3001
|
||||||
|
|
||||||
|
# API URL(可选,会覆盖环境配置)
|
||||||
|
# API_URL=http://localhost:3001/api
|
||||||
|
|
||||||
|
# 浏览器配置
|
||||||
|
HEADLESS=true
|
||||||
|
SLOW_MO=0
|
||||||
|
|
||||||
|
# 测试配置
|
||||||
|
TIMEOUT=120000
|
||||||
|
RETRIES=0
|
||||||
|
|
||||||
|
# 截图和视频配置
|
||||||
|
SCREENSHOT=only-on-failure
|
||||||
|
VIDEO=retain-on-failure
|
||||||
|
TRACE=retain-on-failure
|
||||||
|
|
||||||
|
# CI配置
|
||||||
CI=false
|
CI=false
|
||||||
|
|
||||||
|
# 调试配置
|
||||||
|
DEBUG=false
|
||||||
|
PWDEBUG=false
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# E2E测试环境配置指南
|
||||||
|
|
||||||
|
## 环境说明
|
||||||
|
|
||||||
|
本项目支持三个测试环境:
|
||||||
|
|
||||||
|
- **development**: 本地开发环境 (http://localhost:3001)
|
||||||
|
- **staging**: 预发布环境
|
||||||
|
- **production**: 生产环境
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 配置环境变量
|
||||||
|
|
||||||
|
复制环境变量示例文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp e2e/.env.example e2e/.env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 运行测试
|
||||||
|
|
||||||
|
#### 开发环境测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 默认使用development环境
|
||||||
|
npm run test:e2e
|
||||||
|
|
||||||
|
# 或者显式指定
|
||||||
|
TEST_ENV=development npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 预发布环境测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TEST_ENV=staging npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 生产环境测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TEST_ENV=production npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境配置详解
|
||||||
|
|
||||||
|
### Development环境
|
||||||
|
|
||||||
|
- **baseURL**: http://localhost:3001
|
||||||
|
- **headless**: false (显示浏览器窗口)
|
||||||
|
- **slowMo**: 100ms (减慢操作速度,便于调试)
|
||||||
|
- **retries**: 0 (不重试)
|
||||||
|
- **webServer**: 自动启动开发服务器
|
||||||
|
|
||||||
|
### Staging环境
|
||||||
|
|
||||||
|
- **baseURL**: https://staging.novalon.com
|
||||||
|
- **headless**: true (无头模式)
|
||||||
|
- **slowMo**: 0 (正常速度)
|
||||||
|
- **retries**: 1 (失败重试1次)
|
||||||
|
- **webServer**: 不启动
|
||||||
|
|
||||||
|
### Production环境
|
||||||
|
|
||||||
|
- **baseURL**: https://novalon.com
|
||||||
|
- **headless**: true (无头模式)
|
||||||
|
- **slowMo**: 0 (正常速度)
|
||||||
|
- **retries**: 2 (失败重试2次)
|
||||||
|
- **webServer**: 不启动
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
| 变量名 | 说明 | 默认值 |
|
||||||
|
|--------|------|--------|
|
||||||
|
| TEST_ENV | 测试环境 | development |
|
||||||
|
| BASE_URL | 基础URL | 根据环境配置 |
|
||||||
|
| API_URL | API URL | 根据环境配置 |
|
||||||
|
| HEADLESS | 无头模式 | true |
|
||||||
|
| SLOW_MO | 减慢操作(ms) | 0 |
|
||||||
|
| TIMEOUT | 超时时间(ms) | 120000 |
|
||||||
|
| RETRIES | 重试次数 | 0 |
|
||||||
|
| SCREENSHOT | 截图策略 | only-on-failure |
|
||||||
|
| VIDEO | 视频策略 | retain-on-failure |
|
||||||
|
| TRACE | 追踪策略 | retain-on-failure |
|
||||||
|
| CI | CI环境 | false |
|
||||||
|
| DEBUG | 调试模式 | false |
|
||||||
|
| PWDEBUG | Playwright调试 | false |
|
||||||
|
|
||||||
|
## CI/CD集成
|
||||||
|
|
||||||
|
### Woodpecker CI配置示例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
pipeline:
|
||||||
|
test-smoke:
|
||||||
|
image: mcr.microsoft.com/playwright:v1.48.0-focal
|
||||||
|
commands:
|
||||||
|
- cd e2e
|
||||||
|
- npm ci
|
||||||
|
- TEST_ENV=staging npx playwright test --project=chromium --grep=@smoke
|
||||||
|
when:
|
||||||
|
event: [push, pull_request]
|
||||||
|
|
||||||
|
test-regression:
|
||||||
|
image: mcr.microsoft.com/playwright:v1.48.0-focal
|
||||||
|
commands:
|
||||||
|
- cd e2e
|
||||||
|
- npm ci
|
||||||
|
- TEST_ENV=staging npx playwright test --project=chromium --grep=@regression
|
||||||
|
when:
|
||||||
|
event: [push, pull_request]
|
||||||
|
|
||||||
|
test-full:
|
||||||
|
image: mcr.microsoft.com/playwright:v1.48.0-focal
|
||||||
|
commands:
|
||||||
|
- cd e2e
|
||||||
|
- npm ci
|
||||||
|
- TEST_ENV=production npx playwright test
|
||||||
|
when:
|
||||||
|
event: [deployment]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
### 1. 本地开发
|
||||||
|
|
||||||
|
使用development环境,可以看到浏览器操作过程,便于调试:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TEST_ENV=development npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 代码提交
|
||||||
|
|
||||||
|
在staging环境运行smoke和regression测试:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TEST_ENV=staging npm run test:e2e -- --grep="@smoke|@regression"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 生产部署
|
||||||
|
|
||||||
|
在production环境运行完整测试套件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TEST_ENV=production npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 调试测试
|
||||||
|
|
||||||
|
启用Playwright调试模式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PWDEBUG=1 TEST_ENV=development npm run test:e2e -- --grep="test name"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 问题1: 环境变量不生效
|
||||||
|
|
||||||
|
确保在项目根目录运行命令,或者在e2e目录下运行。
|
||||||
|
|
||||||
|
### 问题2: 开发服务器启动失败
|
||||||
|
|
||||||
|
检查端口3001是否被占用,或者修改配置中的端口。
|
||||||
|
|
||||||
|
### 问题3: 测试超时
|
||||||
|
|
||||||
|
增加TIMEOUT环境变量值:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TIMEOUT=180000 npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题4: 网络问题
|
||||||
|
|
||||||
|
检查网络连接,确保可以访问目标环境URL。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [测试数据管理](./test-data-management.md)
|
||||||
|
- [性能测试指南](./performance-testing.md)
|
||||||
|
- [安全测试指南](./security-testing.md)
|
||||||
|
- [可访问性测试指南](./accessibility-testing.md)
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import { defineConfig, devices } from '@playwright/test';
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
import { getEnvironment } from './src/config/environments';
|
||||||
|
|
||||||
|
const env = getEnvironment();
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
testDir: './src/tests',
|
testDir: './src/tests',
|
||||||
fullyParallel: true,
|
fullyParallel: true,
|
||||||
forbidOnly: !!process.env.CI,
|
forbidOnly: !!process.env.CI,
|
||||||
retries: process.env.CI ? 2 : 0,
|
retries: env.retries,
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 1 : undefined,
|
||||||
reporter: [
|
reporter: [
|
||||||
['html', { open: 'never' }],
|
['html', { open: 'never' }],
|
||||||
@@ -13,19 +16,22 @@ export default defineConfig({
|
|||||||
['line'],
|
['line'],
|
||||||
['list']
|
['list']
|
||||||
],
|
],
|
||||||
timeout: 120000,
|
timeout: env.timeout,
|
||||||
expect: {
|
expect: {
|
||||||
timeout: 30000
|
timeout: 30000
|
||||||
},
|
},
|
||||||
use: {
|
use: {
|
||||||
baseURL: 'http://localhost:3001',
|
baseURL: env.baseURL,
|
||||||
trace: 'retain-on-failure',
|
trace: env.trace,
|
||||||
screenshot: 'only-on-failure',
|
screenshot: env.screenshot,
|
||||||
video: 'retain-on-failure',
|
video: env.video,
|
||||||
headless: true,
|
headless: env.headless,
|
||||||
viewport: { width: 1280, height: 720 },
|
viewport: { width: 1280, height: 720 },
|
||||||
actionTimeout: 30000,
|
actionTimeout: 30000,
|
||||||
navigationTimeout: 60000
|
navigationTimeout: 60000,
|
||||||
|
launchOptions: {
|
||||||
|
slowMo: env.slowMo,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
projects: [
|
projects: [
|
||||||
{
|
{
|
||||||
@@ -49,5 +55,10 @@ export default defineConfig({
|
|||||||
use: { ...devices['iPhone 12'] },
|
use: { ...devices['iPhone 12'] },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webServer: undefined,
|
webServer: env.name === 'development' ? {
|
||||||
|
command: 'npm run dev',
|
||||||
|
url: 'http://localhost:3001',
|
||||||
|
timeout: 120000,
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
} : undefined,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
export interface EnvironmentConfig {
|
||||||
|
name: string;
|
||||||
|
baseURL: string;
|
||||||
|
apiURL: string;
|
||||||
|
timeout: number;
|
||||||
|
retries: number;
|
||||||
|
headless: boolean;
|
||||||
|
slowMo: number;
|
||||||
|
screenshot: 'on' | 'off' | 'only-on-failure';
|
||||||
|
video: 'on' | 'off' | 'retain-on-failure';
|
||||||
|
trace: 'on' | 'off' | 'retain-on-failure';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const environments: Record<string, EnvironmentConfig> = {
|
||||||
|
development: {
|
||||||
|
name: 'development',
|
||||||
|
baseURL: 'http://localhost:3001',
|
||||||
|
apiURL: 'http://localhost:3001/api',
|
||||||
|
timeout: 120000,
|
||||||
|
retries: 0,
|
||||||
|
headless: false,
|
||||||
|
slowMo: 100,
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
video: 'retain-on-failure',
|
||||||
|
trace: 'retain-on-failure',
|
||||||
|
},
|
||||||
|
staging: {
|
||||||
|
name: 'staging',
|
||||||
|
baseURL: 'https://staging.novalon.com',
|
||||||
|
apiURL: 'https://staging.novalon.com/api',
|
||||||
|
timeout: 120000,
|
||||||
|
retries: 1,
|
||||||
|
headless: true,
|
||||||
|
slowMo: 0,
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
video: 'retain-on-failure',
|
||||||
|
trace: 'retain-on-failure',
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
name: 'production',
|
||||||
|
baseURL: 'https://novalon.com',
|
||||||
|
apiURL: 'https://novalon.com/api',
|
||||||
|
timeout: 120000,
|
||||||
|
retries: 2,
|
||||||
|
headless: true,
|
||||||
|
slowMo: 0,
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
video: 'retain-on-failure',
|
||||||
|
trace: 'retain-on-failure',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getEnvironment(): EnvironmentConfig {
|
||||||
|
const envName = process.env.TEST_ENV || 'development';
|
||||||
|
const env = environments[envName];
|
||||||
|
|
||||||
|
if (!env) {
|
||||||
|
throw new Error(`Unknown environment: ${envName}. Valid environments: ${Object.keys(environments).join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBaseURL(): string {
|
||||||
|
return getEnvironment().baseURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getApiURL(): string {
|
||||||
|
return getEnvironment().apiURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDevelopment(): boolean {
|
||||||
|
return getEnvironment().name === 'development';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isStaging(): boolean {
|
||||||
|
return getEnvironment().name === 'staging';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isProduction(): boolean {
|
||||||
|
return getEnvironment().name === 'production';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user