diff --git a/src/hooks/teardown.js b/src/hooks/teardown.js index 881b895..afa691b 100644 --- a/src/hooks/teardown.js +++ b/src/hooks/teardown.js @@ -5,7 +5,14 @@ const testLifecycle = require('./testLifecycle'); * 在所有测试结束后执行 */ async function globalTeardown() { - await testLifecycle.afterAll(); + console.log('开始执行全局清理...'); + try { + await testLifecycle.afterAll(); + console.log('全局清理完成'); + } catch (error) { + console.error('全局清理出错:', error); + throw error; + } } module.exports = globalTeardown; \ No newline at end of file diff --git a/src/hooks/testLifecycle.js b/src/hooks/testLifecycle.js index 30395dc..55ab409 100644 --- a/src/hooks/testLifecycle.js +++ b/src/hooks/testLifecycle.js @@ -10,7 +10,7 @@ const FileUtils = require('../utils/FileUtils'); */ class TestLifecycle { constructor() { - this.reportPath = process.env.PERFORMANCE_REPORT_PATH || './test-results/performance-report.json'; + this.reportPath = process.env.PERFORMANCE_REPORT_PATH || './test-results/performance-report.html'; } /** @@ -25,95 +25,181 @@ class TestLifecycle { console.log('✨ 测试环境初始化完成'); } - /** - * 测试结束后的处理 - * 在所有测试结束后执行,用于生成报告和清理工作 - */ async afterAll() { - const performanceData = performanceService.getPerformanceData(); - const report = this.generateReport(performanceData); - await this.saveReport(report); - console.log(`📊 测试报告已生成: ${this.reportPath}`); + 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 {Array} performanceData 性能数据数组 - * @returns {Object} 测试报告对象 + * @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 = {}; - let totalDuration = 0; - let totalSuccess = 0; - let totalFailure = 0; - - // 统计每个页面的性能数据 performanceData.forEach(record => { - const { pageName, duration, success } = record; - + const { pageName, duration, success, errorMessage } = record; if (!pageStats[pageName]) { pageStats[pageName] = { totalTests: 0, successCount: 0, failureCount: 0, totalDuration: 0, - averageDuration: 0, - minDuration: Infinity, - maxDuration: 0, errors: [] }; } - + const stats = pageStats[pageName]; stats.totalTests++; success ? stats.successCount++ : stats.failureCount++; stats.totalDuration += duration; - stats.minDuration = Math.min(stats.minDuration, duration); - stats.maxDuration = Math.max(stats.maxDuration, duration); - stats.averageDuration = stats.totalDuration / stats.totalTests; - - if (!success && record.errorMessage) { - stats.errors.push({ - timestamp: record.timestamp, - error: record.errorMessage - }); + + if (!success && errorMessage) { + stats.errors.push(errorMessage); } - - // 更新总体统计 - totalDuration += duration; - success ? totalSuccess++ : totalFailure++; }); - // 生成报告 - return { - summary: { - totalTests: performanceData.length, - successCount: totalSuccess, - failureCount: totalFailure, - successRate: (totalSuccess / performanceData.length * 100).toFixed(2) + '%', - averageDuration: totalDuration / performanceData.length, - totalDuration: totalDuration - }, - pageStats, - timestamp: new Date().toISOString(), - rawData: performanceData - }; + // 生成HTML报告 + return ` + + + + + 测试执行报告 + + + +
+
+

测试执行报告

+

执行时间: ${new Date().toLocaleString()}

+
+ +
+
+

总用例数

+

${totalTests}

+
+
+

成功数

+

${successTests}

+
+
+

失败数

+

${failedTests}

+
+
+

成功率

+

${successRate}%

+
+
+

总耗时

+

${(totalDuration / 1000).toFixed(2)}秒

+
+
+ +

页面测试详情

+ + + + + + + + + + + + + ${Object.entries(pageStats).map(([pageName, stats]) => ` + + + + + + + + + `).join('')} + +
页面名称测试数成功数失败数总耗时错误信息
${pageName}${stats.totalTests}${stats.successCount}${stats.failureCount}${(stats.totalDuration / 1000).toFixed(2)}秒 + ${stats.errors.length > 0 ? + `
${stats.errors.join('
')}
` : + ''} +
+ +

详细测试记录

+ + + + + + + + + + + ${performanceData.map(record => ` + + + + + + + `).join('')} + +
页面名称状态耗时错误信息
${record.pageName}${record.success ? '通过' : '失败'}${(record.duration / 1000).toFixed(2)}秒${record.errorMessage || ''}
+
+ +`; } /** * 保存测试报告 - * @param {Object} report 测试报告对象 + * @param {String} report 测试报告字符串 + * @returns {String} 保存后的报告路径 */ async saveReport(report) { try { - await FileUtils.writeJsonFile(this.reportPath, report); + await FileUtils.writeFile(this.reportPath, report); + return this.reportPath; } catch (error) { console.error('保存测试报告失败:', error); + throw error; } } } -// 创建单例实例 -const testLifecycle = new TestLifecycle(); -module.exports = testLifecycle; \ No newline at end of file +module.exports = new TestLifecycle(); \ No newline at end of file diff --git a/src/services/PerformanceService.js b/src/services/PerformanceService.js index b87f590..39577f0 100644 --- a/src/services/PerformanceService.js +++ b/src/services/PerformanceService.js @@ -99,7 +99,17 @@ class PerformanceService { * @returns {Array} 性能数据数组 */ getPerformanceData() { - return this.performanceData; + try { + // 从文件读取最新数据 + const data = FileUtils.loadFromJsonFile(this.performanceDataPath); + if (data) { + this.performanceData = data; + } + return this.performanceData; + } catch (error) { + console.error('读取性能数据失败:', error); + return this.performanceData; + } } } diff --git a/src/utils/FileUtils.js b/src/utils/FileUtils.js index 83f423f..794b7d6 100644 --- a/src/utils/FileUtils.js +++ b/src/utils/FileUtils.js @@ -3,6 +3,7 @@ * 提供文件读写、目录创建等常用操作 */ const fs = require('fs').promises; +const fsSync = require('fs'); const path = require('path'); class FileUtils { @@ -40,15 +41,18 @@ class FileUtils { * @param {Object} data 要写入的数据 */ static async writeJsonFile(filePath, data) { - try { - // 确保目录存在 - await this.ensureDirectoryExists(path.dirname(filePath)); - // 写入文件 - await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8'); - } catch (error) { - console.error(`写入JSON文件失败 [${filePath}]:`, error); - throw error; - } + await this.ensureDirectoryExists(path.dirname(filePath)); + await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8'); + } + + /** + * 写入文本文件 + * @param {string} filePath 文件路径 + * @param {string} content 要写入的内容 + */ + static async writeFile(filePath, content) { + await this.ensureDirectoryExists(path.dirname(filePath)); + await fs.writeFile(filePath, content, 'utf8'); } /** @@ -84,15 +88,10 @@ class FileUtils { /** * 检查文件是否存在 * @param {string} filePath 文件路径 - * @returns {Promise} 文件是否存在 + * @returns {boolean} 文件是否存在 */ - static async fileExists(filePath) { - try { - await fs.access(filePath); - return true; - } catch { - return false; - } + static fileExists(filePath) { + return fsSync.existsSync(filePath); } /** @@ -126,21 +125,17 @@ class FileUtils { /** * 从JSON文件加载对象 * @param {string} filePath 文件路径 - * @param {Object} options 选项 - * @param {string} options.encoding 文件编码 (默认: 'utf8') * @returns {Object|null} 加载的对象,如果失败则返回null */ - static loadFromJsonFile(filePath, options = {}) { + static loadFromJsonFile(filePath) { try { - const {encoding = 'utf8'} = options; - - if (!fs.existsSync(filePath)) { - console.error(`文件不存在: ${filePath}`); + if (!this.fileExists(filePath)) { + console.warn(`文件不存在: ${filePath}`); return null; } - const data = fs.readFileSync(filePath, encoding); - return JSON.parse(data); + const content = fsSync.readFileSync(filePath, 'utf8'); + return JSON.parse(content); } catch (error) { console.error(`加载JSON文件失败: ${filePath}`, error); return null; diff --git a/test-data/menu-data.json b/test-data/menu-data.json index 2bd33d8..205194f 100644 --- a/test-data/menu-data.json +++ b/test-data/menu-data.json @@ -1,8 +1,14 @@ [ - { - "id": 7, - "text": "电池投放计划", - "path": "电池投放计划", - "hasThirdMenu": true - } + { + "id": 1, + "text": "主数据", + "path": "主数据", + "hasThirdMenu": true + }, + { + "id": 2, + "text": "业务数据", + "path": "业务数据", + "hasThirdMenu": true + } ] \ No newline at end of file diff --git a/test-data/test-progress.json b/test-data/test-progress.json index 71a8711..0637a08 100644 --- a/test-data/test-progress.json +++ b/test-data/test-progress.json @@ -1,3 +1 @@ -[ - 7 -] \ No newline at end of file +[] \ No newline at end of file