5d5b7feb0a
添加Playwright测试框架配置和基础页面对象 实现冒烟测试用例覆盖首页和联系页面核心功能 更新导航组件以支持滚动高亮功能 添加BackButton组件统一返回按钮行为 配置Woodpecker CI集成和测试报告生成
148 lines
5.0 KiB
JavaScript
148 lines
5.0 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
const { spawn } = require('child_process');
|
||
const fs = require('fs');
|
||
const { glob } = require('glob');
|
||
|
||
const testTypes = [
|
||
{ name: '冒烟测试', script: 'test:smoke', pattern: 'src/tests/smoke/**/*.spec.ts' },
|
||
{ name: '回归测试', script: 'test:regression', pattern: 'src/tests/regression/**/*.spec.ts' },
|
||
{ name: '性能测试', script: 'test:performance', pattern: 'src/tests/performance/**/*.spec.ts' },
|
||
{ name: '响应式测试', script: 'test:responsive', pattern: 'src/tests/responsive/**/*.spec.ts' }
|
||
];
|
||
|
||
const TIMEOUT_SECONDS = 600;
|
||
|
||
async function runTests() {
|
||
console.log('🧪 开始运行E2E测试...\n');
|
||
|
||
const results = {
|
||
total: 0,
|
||
passed: 0,
|
||
failed: 0,
|
||
byType: {}
|
||
};
|
||
|
||
for (const testType of testTypes) {
|
||
console.log(`\n${'='.repeat(60)}`);
|
||
console.log(`📋 ${testType.name}`);
|
||
console.log(`${'='.repeat(60)}`);
|
||
|
||
await new Promise((resolve) => {
|
||
const startTime = Date.now();
|
||
let lastUpdateTime = startTime;
|
||
let currentTest = 0;
|
||
let passedCount = 0;
|
||
let failedCount = 0;
|
||
let isComplete = false;
|
||
let lastTestName = '';
|
||
|
||
const testProcess = spawn('npm', ['run', testType.script], {
|
||
cwd: __dirname,
|
||
shell: true,
|
||
stdio: ['pipe', 'pipe', 'pipe']
|
||
});
|
||
|
||
testProcess.stdout.on('data', (data) => {
|
||
const output = data.toString();
|
||
|
||
if (output.includes('›')) {
|
||
currentTest++;
|
||
const progress = Math.min(100, Math.round((currentTest / 100) * 100));
|
||
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
||
const barLength = Math.floor(progress / 2);
|
||
const bar = '█'.repeat(barLength) + '░'.repeat(50 - barLength);
|
||
|
||
const testNameMatch = output.match(/›\s+(.+)/);
|
||
if (testNameMatch) {
|
||
lastTestName = testNameMatch[1].trim();
|
||
}
|
||
|
||
process.stdout.write(`\r⏳ 进度: [${bar}] ${progress}% - ${elapsed}s - ${lastTestName}`);
|
||
lastUpdateTime = Date.now();
|
||
}
|
||
|
||
if (output.includes('passed')) {
|
||
const match = output.match(/(\d+)\s+passed/);
|
||
if (match) {
|
||
passedCount = parseInt(match[1]);
|
||
}
|
||
}
|
||
|
||
if (output.includes('failed')) {
|
||
const match = output.match(/(\d+)\s+failed/);
|
||
if (match) {
|
||
failedCount = parseInt(match[1]);
|
||
}
|
||
}
|
||
});
|
||
|
||
testProcess.stderr.on('data', (data) => {
|
||
const output = data.toString();
|
||
if (output.includes('Error') || output.includes('error')) {
|
||
process.stdout.write('\n❌ 错误: ' + output);
|
||
}
|
||
});
|
||
|
||
testProcess.on('close', (code) => {
|
||
isComplete = true;
|
||
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
||
process.stdout.write(`\r✅ 完成: [${'█'.repeat(50)}] 100% - ${elapsed}s\n`);
|
||
|
||
results.total += passedCount + failedCount;
|
||
results.passed += passedCount;
|
||
results.failed += failedCount;
|
||
results.byType[testType.name] = {
|
||
total: passedCount + failedCount,
|
||
passed: passedCount,
|
||
failed: failedCount,
|
||
elapsed: elapsed
|
||
};
|
||
|
||
resolve();
|
||
});
|
||
|
||
const progressInterval = setInterval(() => {
|
||
if (!isComplete) {
|
||
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
||
const timeSinceLastUpdate = Date.now() - lastUpdateTime;
|
||
|
||
if (timeSinceLastUpdate > 10000 && timeSinceLastUpdate < 30000) {
|
||
process.stdout.write(`\r⏳ 等待测试... (${elapsed}s) - ${lastTestName}`);
|
||
} else if (timeSinceLastUpdate >= 30000) {
|
||
process.stdout.write(`\r⚠️ 测试可能卡住 (${elapsed}s) - ${lastTestName}`);
|
||
}
|
||
|
||
if (elapsed > TIMEOUT_SECONDS) {
|
||
console.log(`\n❌ 测试超时 (${TIMEOUT_SECONDS}s),正在停止...`);
|
||
testProcess.kill();
|
||
clearInterval(progressInterval);
|
||
isComplete = true;
|
||
resolve();
|
||
}
|
||
}
|
||
}, 5000);
|
||
|
||
testProcess.on('close', () => {
|
||
clearInterval(progressInterval);
|
||
});
|
||
});
|
||
}
|
||
|
||
console.log(`\n${'='.repeat(60)}`);
|
||
console.log('📊 测试结果汇总');
|
||
console.log(`${'='.repeat(60)}`);
|
||
console.log(`总测试数: ${results.total}`);
|
||
console.log(`通过: ${results.passed} (${((results.passed / results.total) * 100).toFixed(1)}%)`);
|
||
console.log(`失败: ${results.failed} (${((results.failed / results.total) * 100).toFixed(1)}%)`);
|
||
|
||
console.log('\n分类结果:');
|
||
for (const [name, result] of Object.entries(results.byType)) {
|
||
const passRate = ((result.passed / result.total) * 100).toFixed(1);
|
||
const status = passRate >= 80 ? '✅' : passRate >= 50 ? '⚠️' : '❌';
|
||
console.log(` ${status} ${name}: ${result.passed}/${result.total} (${passRate}%) - ${result.elapsed}s`);
|
||
}
|
||
}
|
||
|
||
runTests().catch(console.error);
|