feat: add Woodpecker CI configuration for tiered testing
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const resultsDir = 'test-results';
|
||||
const reportDir = 'test-results';
|
||||
|
||||
console.log('📊 生成测试报告...');
|
||||
|
||||
if (!fs.existsSync(resultsDir)) {
|
||||
console.log('❌ 测试结果目录不存在');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const jsonFiles = fs.readdirSync(resultsDir)
|
||||
.filter(file => file.endsWith('.json') && file.includes('-results.json'));
|
||||
|
||||
if (jsonFiles.length === 0) {
|
||||
console.log('❌ 未找到测试结果文件');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`📁 找到 ${jsonFiles.length} 个测试结果文件`);
|
||||
|
||||
const allResults = [];
|
||||
for (const file of jsonFiles) {
|
||||
const filePath = path.join(resultsDir, file);
|
||||
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
||||
|
||||
if (data.suites) {
|
||||
for (const suite of data.suites) {
|
||||
for (const spec of suite.suites) {
|
||||
for (const test of spec.tests) {
|
||||
const result = test.results[0];
|
||||
allResults.push({
|
||||
testId: `${spec.file}::${test.title}`,
|
||||
file: spec.file,
|
||||
title: test.title,
|
||||
status: result.status,
|
||||
duration: result.duration,
|
||||
tier: file.includes('fast') ? 'fast' : file.includes('deep') ? 'deep' : 'standard',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const report = {
|
||||
timestamp: new Date().toISOString(),
|
||||
total: {
|
||||
name: 'total',
|
||||
total: allResults.length,
|
||||
passed: allResults.filter(r => r.status === 'passed').length,
|
||||
failed: allResults.filter(r => r.status === 'failed').length,
|
||||
skipped: allResults.filter(r => r.status === 'skipped').length,
|
||||
duration: allResults.reduce((sum, r) => sum + r.duration, 0),
|
||||
},
|
||||
tiers: {
|
||||
fast: allResults.filter(r => r.tier === 'fast').reduce((acc, r) => ({
|
||||
name: 'fast',
|
||||
total: acc.total + 1,
|
||||
passed: acc.passed + (r.status === 'passed' ? 1 : 0),
|
||||
failed: acc.failed + (r.status === 'failed' ? 1 : 0),
|
||||
duration: acc.duration + r.duration,
|
||||
}), { name: 'fast', total: 0, passed: 0, failed: 0, duration: 0 }),
|
||||
standard: allResults.filter(r => r.tier === 'standard').reduce((acc, r) => ({
|
||||
name: 'standard',
|
||||
total: acc.total + 1,
|
||||
passed: acc.passed + (r.status === 'passed' ? 1 : 0),
|
||||
failed: acc.failed + (r.status === 'failed' ? 1 : 0),
|
||||
duration: acc.duration + r.duration,
|
||||
}), { name: 'standard', total: 0, passed: 0, failed: 0, duration: 0 }),
|
||||
deep: allResults.filter(r => r.tier === 'deep').reduce((acc, r) => ({
|
||||
name: 'deep',
|
||||
total: acc.total + 1,
|
||||
passed: acc.passed + (r.status === 'passed' ? 1 : 0),
|
||||
failed: acc.failed + (r.status === 'failed' ? 1 : 0),
|
||||
duration: acc.duration + r.duration,
|
||||
}), { name: 'deep', total: 0, passed: 0, failed: 0, duration: 0 }),
|
||||
},
|
||||
failedTests: allResults.filter(r => r.status === 'failed'),
|
||||
slowTests: allResults.filter(r => r.duration > 120000),
|
||||
};
|
||||
|
||||
report.total.avgDuration = report.total.duration / report.total.total;
|
||||
|
||||
const reportPath = path.join(reportDir, 'ci-report.json');
|
||||
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
||||
|
||||
console.log('✅ 测试报告生成完成');
|
||||
console.log(` 总测试数: ${report.total.total}`);
|
||||
console.log(` 通过: ${report.total.passed}`);
|
||||
console.log(` 失败: ${report.total.failed}`);
|
||||
console.log(` 总耗时: ${(report.total.duration / 1000).toFixed(2)}s`);
|
||||
|
||||
if (report.total.failed > 0) {
|
||||
console.log(`\n❌ 发现 ${report.total.failed} 个失败测试`);
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user