feat: configure UAT test automation and reporting
This commit is contained in:
@@ -67,6 +67,26 @@ pipeline:
|
||||
depends_on:
|
||||
- start-test-env
|
||||
|
||||
# UAT测试阶段
|
||||
uat-tests:
|
||||
image: mcr.microsoft.com/playwright:v1.58.2-jammy
|
||||
group: uat
|
||||
environment:
|
||||
TEST_BASE_URL: http://frontend-test:80
|
||||
API_BASE_URL: http://backend-test:8080
|
||||
HEADLESS_BROWSER: "true"
|
||||
CI: true
|
||||
commands:
|
||||
- cd uat-tests
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npx playwright test --config=playwright.config.ts --reporter=json --reporter=html --reporter=junit
|
||||
- node quality-gate.js
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
depends_on:
|
||||
- start-test-env
|
||||
|
||||
# 性能测试阶段
|
||||
performance-tests:
|
||||
image: node:18-alpine
|
||||
@@ -80,6 +100,8 @@ pipeline:
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
branch: [main, develop]
|
||||
depends_on:
|
||||
- uat-tests
|
||||
|
||||
# 质量门禁检查
|
||||
quality-gate:
|
||||
@@ -119,6 +141,7 @@ pipeline:
|
||||
depends_on:
|
||||
- quality-gate
|
||||
- trend-analysis
|
||||
- uat-tests
|
||||
|
||||
# 生成测试报告
|
||||
generate-reports:
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# UAT Test Suite
|
||||
|
||||
UAT测试套件用于验证Novalon管理系统的用户验收测试场景。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
uat-tests/
|
||||
├── config/ # 配置文件
|
||||
│ └── uat-config.ts # UAT配置
|
||||
├── data/ # 测试数据
|
||||
│ ├── users.json # 用户数据
|
||||
│ ├── roles.json # 角色数据
|
||||
│ └── scenarios.json # 场景数据
|
||||
├── scenarios/ # 测试场景
|
||||
│ ├── user-lifecycle/ # 用户生命周期场景
|
||||
│ ├── role-management/ # 角色管理场景
|
||||
│ ├── collaboration/ # 多角色协作场景
|
||||
│ ├── permission/ # 权限验证场景
|
||||
│ └── audit/ # 审计场景
|
||||
├── utils/ # 工具类
|
||||
│ ├── uat-helper.ts # UAT辅助工具
|
||||
│ ├── scenario-runner.ts # 场景运行器
|
||||
│ └── data-loader.ts # 数据加载器
|
||||
├── pages/ # 页面对象
|
||||
│ └── UserManagementPage.ts
|
||||
├── screenshots/ # 截图目录
|
||||
├── test-results/ # 测试结果
|
||||
├── playwright.config.ts # Playwright配置
|
||||
├── run-uat-tests.sh # 测试运行脚本
|
||||
├── quality-gate.js # 质量门禁检查
|
||||
└── package.json # 依赖配置
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
cd uat-tests
|
||||
npm install
|
||||
npx playwright install --with-deps
|
||||
```
|
||||
|
||||
### 配置环境变量
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# 编辑.env文件,设置测试环境URL
|
||||
```
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有UAT测试
|
||||
npm run test
|
||||
|
||||
# 运行特定场景
|
||||
npx playwright test scenarios/user-lifecycle/
|
||||
|
||||
# 调试模式
|
||||
npm run test:debug
|
||||
|
||||
# 查看测试报告
|
||||
npm run test:report
|
||||
```
|
||||
|
||||
## 测试场景
|
||||
|
||||
### 用户生命周期场景
|
||||
|
||||
- 新用户注册与激活
|
||||
- 用户信息变更
|
||||
- 用户角色演进
|
||||
|
||||
### 角色管理场景
|
||||
|
||||
- 角色分配与权限验证
|
||||
|
||||
### 多角色协作场景
|
||||
|
||||
- 跨部门协作流程
|
||||
- 数据一致性验证
|
||||
|
||||
## 质量门禁
|
||||
|
||||
质量门禁标准:
|
||||
|
||||
- 通过率 >= 95%
|
||||
- 不稳定率 <= 5%
|
||||
- 执行时间 <= 10分钟
|
||||
|
||||
运行质量门禁检查:
|
||||
|
||||
```bash
|
||||
npm run test:quality-gate
|
||||
```
|
||||
|
||||
## CI/CD集成
|
||||
|
||||
UAT测试已集成到Woodpecker CI/CD流水线中,在每次push和pull request时自动运行。
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **测试数据隔离**:每个测试使用独立的数据,避免相互影响
|
||||
2. **智能等待**:使用UATHelper提供的智能等待方法,避免固定等待
|
||||
3. **截图记录**:测试失败时自动截图,便于调试
|
||||
4. **并行执行**:支持多worker并行执行,提高测试效率
|
||||
5. **跨浏览器测试**:支持Chrome、Firefox、Safari浏览器测试
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 测试失败
|
||||
|
||||
1. 查看测试报告:`npm run test:report`
|
||||
2. 检查截图:`screenshots/`目录
|
||||
3. 查看日志:`test-results/`目录
|
||||
|
||||
### 环境问题
|
||||
|
||||
确保测试环境已启动:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
docker-compose -f docker-compose.test.yml up -d
|
||||
```
|
||||
|
||||
## 贡献指南
|
||||
|
||||
添加新的UAT测试场景:
|
||||
|
||||
1. 在`scenarios/`目录下创建新的场景文件
|
||||
2. 使用`ScenarioRunner`和`UATHelper`工具
|
||||
3. 遵循现有的测试模式和命名约定
|
||||
4. 添加相应的测试数据到`data/`目录
|
||||
|
||||
## 许可证
|
||||
|
||||
Copyright © 2024 Novalon. All rights reserved.
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "novalon-uat-tests",
|
||||
"version": "1.0.0",
|
||||
"description": "UAT test suite for Novalon Management System",
|
||||
"scripts": {
|
||||
"test": "playwright test",
|
||||
"test:headed": "playwright test --headed",
|
||||
"test:debug": "playwright test --debug",
|
||||
"test:report": "playwright show-report",
|
||||
"test:quality-gate": "node quality-gate.js",
|
||||
"install-browsers": "playwright install --with-deps"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.40.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './uat-tests/scenarios',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 4 : 8,
|
||||
reporter: [
|
||||
['html', { outputFolder: 'uat-tests/test-results/html-report' }],
|
||||
['json', { outputFile: 'uat-tests/test-results/results.json' }],
|
||||
['junit', { outputFile: 'uat-tests/test-results/junit.xml' }],
|
||||
['list']
|
||||
],
|
||||
use: {
|
||||
baseURL: process.env.TEST_BASE_URL || 'http://localhost:3001',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
headless: process.env.HEADLESS_BROWSER === 'true',
|
||||
actionTimeout: parseInt(process.env.TEST_TIMEOUT || '30000'),
|
||||
navigationTimeout: parseInt(process.env.TEST_TIMEOUT || '30000'),
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
outputDir: 'uat-tests/test-results/artifacts',
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const resultsPath = path.join(__dirname, 'test-results', 'results.json');
|
||||
const qualityGateThresholds = {
|
||||
passRate: 95,
|
||||
flakyRate: 5,
|
||||
duration: 600000
|
||||
};
|
||||
|
||||
function loadTestResults() {
|
||||
if (!fs.existsSync(resultsPath)) {
|
||||
console.error('❌ Test results not found!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = fs.readFileSync(resultsPath, 'utf-8');
|
||||
return JSON.parse(data);
|
||||
}
|
||||
|
||||
function calculateMetrics(results) {
|
||||
const totalTests = results.stats.expected;
|
||||
const passedTests = results.stats.expected - results.stats.failed;
|
||||
const failedTests = results.stats.failed;
|
||||
const flakyTests = results.stats.flaky;
|
||||
const duration = results.stats.duration;
|
||||
|
||||
const passRate = (passedTests / totalTests) * 100;
|
||||
const flakyRate = (flakyTests / totalTests) * 100;
|
||||
|
||||
return {
|
||||
totalTests,
|
||||
passedTests,
|
||||
failedTests,
|
||||
flakyTests,
|
||||
duration,
|
||||
passRate: passRate.toFixed(2),
|
||||
flakyRate: flakyRate.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
function checkQualityGate(metrics) {
|
||||
const failures = [];
|
||||
|
||||
if (metrics.passRate < qualityGateThresholds.passRate) {
|
||||
failures.push(`Pass rate (${metrics.passRate}%) is below threshold (${qualityGateThresholds.passRate}%)`);
|
||||
}
|
||||
|
||||
if (metrics.flakyRate > qualityGateThresholds.flakyRate) {
|
||||
failures.push(`Flaky rate (${metrics.flakyRate}%) is above threshold (${qualityGateThresholds.flakyRate}%)`);
|
||||
}
|
||||
|
||||
if (metrics.duration > qualityGateThresholds.duration) {
|
||||
failures.push(`Test duration (${metrics.duration}ms) exceeds threshold (${qualityGateThresholds.duration}ms)`);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('🚦 Checking UAT Quality Gate...\n');
|
||||
|
||||
const results = loadTestResults();
|
||||
const metrics = calculateMetrics(results);
|
||||
const failures = checkQualityGate(metrics);
|
||||
|
||||
console.log('📊 Test Metrics:');
|
||||
console.log(` Total Tests: ${metrics.totalTests}`);
|
||||
console.log(` Passed: ${metrics.passedTests}`);
|
||||
console.log(` Failed: ${metrics.failedTests}`);
|
||||
console.log(` Flaky: ${metrics.flakyTests}`);
|
||||
console.log(` Pass Rate: ${metrics.passRate}%`);
|
||||
console.log(` Flaky Rate: ${metrics.flakyRate}%`);
|
||||
console.log(` Duration: ${metrics.duration}ms\n`);
|
||||
|
||||
if (failures.length === 0) {
|
||||
console.log('✅ Quality Gate Passed!');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log('❌ Quality Gate Failed:');
|
||||
failures.forEach(failure => console.log(` - ${failure}`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting UAT Test Suite..."
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "⚠️ Warning: .env file not found, using default values"
|
||||
cp .env.example .env
|
||||
fi
|
||||
|
||||
export $(cat .env | xargs)
|
||||
|
||||
echo "📊 Running UAT tests..."
|
||||
npx playwright test --config=playwright.config.ts
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ All UAT tests passed!"
|
||||
echo "📈 Generating test report..."
|
||||
npx playwright show-report uat-tests/test-results/html-report
|
||||
else
|
||||
echo "❌ Some tests failed. Check the report for details."
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user