180 lines
6.4 KiB
JavaScript
180 lines
6.4 KiB
JavaScript
const performanceService = require('../services/PerformanceService');
|
|
const FileUtils = require('../utils/FileUtils');
|
|
|
|
/**
|
|
* 测试生命周期管理
|
|
* 负责管理测试的全局生命周期,包括:
|
|
* 1. 测试开始前的初始化工作
|
|
* 2. 测试结束后的清理和报告生成
|
|
* 3. 其他全局测试设置
|
|
*/
|
|
class TestLifecycle {
|
|
constructor() {
|
|
this.reportPath = process.env.PERFORMANCE_REPORT_PATH || './test-results/performance-report.html';
|
|
}
|
|
|
|
/**
|
|
* 测试开始前的初始化
|
|
* 在所有测试开始前执行,用于准备测试环境
|
|
*/
|
|
async beforeAll() {
|
|
// 确保测试结果目录存在
|
|
await FileUtils.ensureDirectoryExists('./test-results');
|
|
// 清空之前的性能数据
|
|
await performanceService.clearPerformanceData();
|
|
console.log('✨ 测试环境初始化完成');
|
|
}
|
|
|
|
async afterAll() {
|
|
console.log('开始生成测试报告...');
|
|
try {
|
|
const performanceData = performanceService.getPerformanceData();
|
|
console.log('获取到性能数据:', performanceData.length, '条记录');
|
|
const report = this.generateReport(performanceData);
|
|
await this.saveReport(report);
|
|
console.log(`📊 测试报告已生成: ${this.reportPath}`);
|
|
} catch (error) {
|
|
console.error('生成测试报告出错:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 生成测试报告
|
|
* @param {Object} data 性能数据对象
|
|
* @returns {String} 测试报告字符串
|
|
*/
|
|
generateReport(performanceData) {
|
|
// 统计数据
|
|
const totalTests = performanceData.length;
|
|
const successTests = performanceData.filter(record => record.success).length;
|
|
const failedTests = totalTests - successTests;
|
|
const successRate = totalTests > 0 ? ((successTests / totalTests) * 100).toFixed(2) : '0.00';
|
|
const totalDuration = performanceData.reduce((sum, record) => sum + record.duration, 0);
|
|
|
|
// 按页面分组统计
|
|
const pageStats = {};
|
|
performanceData.forEach(record => {
|
|
const { pageName, duration, success, errorMessage } = record;
|
|
if (!pageStats[pageName]) {
|
|
pageStats[pageName] = {
|
|
totalTests: 0,
|
|
successCount: 0,
|
|
failureCount: 0,
|
|
totalDuration: 0,
|
|
errors: []
|
|
};
|
|
}
|
|
|
|
const stats = pageStats[pageName];
|
|
stats.totalTests++;
|
|
success ? stats.successCount++ : stats.failureCount++;
|
|
stats.totalDuration += duration;
|
|
|
|
if (!success && errorMessage) {
|
|
stats.errors.push(errorMessage);
|
|
}
|
|
});
|
|
|
|
// 生成HTML报告
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>测试执行报告</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
|
|
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.header { text-align: center; margin-bottom: 30px; }
|
|
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
|
.summary-item { background: #f8f9fa; padding: 15px; border-radius: 6px; text-align: center; }
|
|
.success { color: #28a745; }
|
|
.failure { color: #dc3545; }
|
|
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
|
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #dee2e6; }
|
|
th { background: #f8f9fa; }
|
|
tr:hover { background: #f8f9fa; }
|
|
.status-true { color: #28a745; }
|
|
.status-false { color: #dc3545; }
|
|
.error-list { color: #dc3545; margin-top: 5px; font-size: 0.9em; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>测试执行报告</h1>
|
|
<p>执行时间: ${new Date().toLocaleString()}</p>
|
|
</div>
|
|
|
|
<div class="summary">
|
|
<div class="summary-item">
|
|
<h3>总用例数</h3>
|
|
<p>${totalTests}</p>
|
|
</div>
|
|
<div class="summary-item success">
|
|
<h3>成功数</h3>
|
|
<p>${successTests}</p>
|
|
</div>
|
|
<div class="summary-item failure">
|
|
<h3>失败数</h3>
|
|
<p>${failedTests}</p>
|
|
</div>
|
|
<div class="summary-item">
|
|
<h3>成功率</h3>
|
|
<p>${successRate}%</p>
|
|
</div>
|
|
<div class="summary-item">
|
|
<h3>总耗时</h3>
|
|
<p>${(totalDuration / 1000).toFixed(2)}秒</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>测试执行详情</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>页面名称</th>
|
|
<th>测试结果</th>
|
|
<th>执行时间</th>
|
|
<th>成功数/总数</th>
|
|
<th>错误信息</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${performanceData.map(record => {
|
|
const stats = pageStats[record.pageName];
|
|
return `
|
|
<tr>
|
|
<td>${record.pageName}</td>
|
|
<td class="status-${record.success}">${record.success ? '通过' : '失败'}</td>
|
|
<td>${(record.duration / 1000).toFixed(2)}秒</td>
|
|
<td>${stats ? `${stats.successCount}/${stats.totalTests}` : '0/0'}</td>
|
|
<td class="status-false">${record.errorMessage || ''}</td>
|
|
</tr>
|
|
`;
|
|
}).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html>`;
|
|
}
|
|
|
|
/**
|
|
* 保存测试报告
|
|
* @param {String} report 测试报告字符串
|
|
* @returns {String} 保存后的报告路径
|
|
*/
|
|
async saveReport(report) {
|
|
try {
|
|
await FileUtils.writeFile(this.reportPath, report);
|
|
return this.reportPath;
|
|
} catch (error) {
|
|
console.error('保存测试报告失败:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = new TestLifecycle();
|