feat: configure UAT test automation and reporting
This commit is contained in:
@@ -67,6 +67,26 @@ pipeline:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- start-test-env
|
- 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:
|
performance-tests:
|
||||||
image: node:18-alpine
|
image: node:18-alpine
|
||||||
@@ -80,6 +100,8 @@ pipeline:
|
|||||||
when:
|
when:
|
||||||
event: [push, pull_request]
|
event: [push, pull_request]
|
||||||
branch: [main, develop]
|
branch: [main, develop]
|
||||||
|
depends_on:
|
||||||
|
- uat-tests
|
||||||
|
|
||||||
# 质量门禁检查
|
# 质量门禁检查
|
||||||
quality-gate:
|
quality-gate:
|
||||||
@@ -119,6 +141,7 @@ pipeline:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- quality-gate
|
- quality-gate
|
||||||
- trend-analysis
|
- trend-analysis
|
||||||
|
- uat-tests
|
||||||
|
|
||||||
# 生成测试报告
|
# 生成测试报告
|
||||||
generate-reports:
|
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