/** * 集成测试和性能优化模块 * 对所有事件处理器进行集成测试、性能监控和优化建议 */ import { eventBus } from '../eventBus.js'; import { panelHandler, PANEL_EVENT_TYPES } from './PanelHandler.js'; import tabPageHandler, { TABPAGE_EVENT_TYPES } from './TabPageHandler.js'; import areaHandler, { AREA_EVENT_TYPES } from './AreaHandler.js'; import globalEventManager, { GLOBAL_EVENT_TYPES, globalEventActions } from './GlobalEventManager.js'; import dragStateManager, { DRAG_STATE_TYPES, dragStateActions } from './DragStateManager.js'; // 测试配置 export const TEST_CONFIG = { // 测试环境配置 testEnvironment: 'development', // 性能阈值配置 performanceThresholds: { eventEmitTime: 10, // 事件发射时间阈值(毫秒) eventHandleTime: 50, // 事件处理时间阈值(毫秒) memoryUsage: 50 * 1024 * 1024, // 内存使用阈值(50MB) cpuUsage: 80, // CPU使用率阈值(%) dragFPS: 30, // 拖拽帧率阈值 dragDuration: 3000, // 拖拽持续时间阈值(毫秒) concurrentEvents: 100 // 并发事件数量阈值 }, // 测试用例配置 testCases: { // Panel相关测试用例 panel: { createPanel: { priority: 1, timeout: 5000 }, destroyPanel: { priority: 1, timeout: 5000 }, maximizePanel: { priority: 1, timeout: 3000 }, minimizePanel: { priority: 1, timeout: 3000 }, restorePanel: { priority: 1, timeout: 3000 }, closePanel: { priority: 1, timeout: 5000 } }, // TabPage相关测试用例 tabpage: { createTabPage: { priority: 1, timeout: 5000 }, destroyTabPage: { priority: 1, timeout: 5000 }, switchTabPage: { priority: 1, timeout: 3000 }, closeTabPage: { priority: 1, timeout: 5000 }, moveTabPage: { priority: 1, timeout: 5000 } }, // Area相关测试用例 area: { createArea: { priority: 1, timeout: 5000 }, destroyArea: { priority: 1, timeout: 5000 }, dockArea: { priority: 1, timeout: 8000 }, mergeArea: { priority: 1, timeout: 10000 }, splitArea: { priority: 1, timeout: 8000 } }, // 拖拽相关测试用例 drag: { panelDrag: { priority: 1, timeout: 10000 }, tabpageDrag: { priority: 1, timeout: 10000 }, areaDrag: { priority: 1, timeout: 15000 }, multiDrag: { priority: 1, timeout: 20000 } }, // 集成测试用例 integration: { panelTabpage: { priority: 1, timeout: 10000 }, areaPanel: { priority: 1, timeout: 15000 }, crossComponent: { priority: 1, timeout: 20000 }, concurrentEvents: { priority: 1, timeout: 30000 } } } }; // 测试结果类 class TestResult { constructor(testName, testType) { this.testName = testName; this.testType = testType; this.startTime = Date.now(); this.endTime = null; this.duration = 0; this.status = 'pending'; // pending, running, passed, failed, timeout this.error = null; this.metrics = { eventCount: 0, handledEvents: 0, failedEvents: 0, averageHandleTime: 0, maxHandleTime: 0, minHandleTime: Infinity, memoryUsage: { before: null, after: null, delta: null }, performance: { eventEmitTimes: [], eventHandleTimes: [], fps: [] } }; this.events = []; this.assertions = []; } /** * 添加事件 * @param {Object} event - 事件对象 */ addEvent(event) { this.events.push({ ...event, timestamp: Date.now() }); this.metrics.eventCount++; } /** * 记录事件处理 * @param {boolean} success - 是否成功 * @param {number} handleTime - 处理时间 * @param {Object} data - 附加数据 */ recordHandle(success, handleTime, data = {}) { this.metrics.handledEvents++; if (!success) { this.metrics.failedEvents++; } this.metrics.eventHandleTimes.push(handleTime); this.metrics.maxHandleTime = Math.max(this.metrics.maxHandleTime, handleTime); this.metrics.minHandleTime = Math.min(this.metrics.minHandleTime, handleTime); } /** * 记录性能指标 * @param {Object} performance - 性能数据 */ recordPerformance(performance) { Object.assign(this.metrics.performance, performance); } /** * 添加断言 * @param {boolean} condition - 断言条件 * @param {string} message - 断言消息 * @param {Object} expected - 期望值 * @param {Object} actual - 实际值 */ addAssertion(condition, message, expected = null, actual = null) { this.assertions.push({ condition, message, expected, actual, timestamp: Date.now() }); if (!condition) { this.status = 'failed'; this.error = `断言失败: ${message}`; } } /** * 标记为完成 * @param {string} status - 完成状态 * @param {Error} error - 错误信息 */ complete(status = 'passed', error = null) { this.endTime = Date.now(); this.duration = this.endTime - this.startTime; this.status = status; this.error = error; // 计算平均处理时间 if (this.metrics.eventHandleTimes.length > 0) { this.metrics.averageHandleTime = this.metrics.eventHandleTimes.reduce((sum, time) => sum + time, 0) / this.metrics.eventHandleTimes.length; } } /** * 获取测试摘要 * @returns {Object} 测试摘要 */ getSummary() { const passedAssertions = this.assertions.filter(a => a.condition).length; const totalAssertions = this.assertions.length; const successRate = totalAssertions > 0 ? (passedAssertions / totalAssertions) * 100 : 100; return { testName: this.testName, testType: this.testType, status: this.status, duration: this.duration, error: this.error, metrics: { ...this.metrics, eventCount: this.events.length, successRate: successRate, assertionResults: { passed: passedAssertions, failed: totalAssertions - passedAssertions, total: totalAssertions } } }; } } // 性能监控器 class PerformanceMonitor { constructor() { this.metrics = new Map(); this.alerts = []; this.monitoringActive = false; this.memorySamples = []; this.performanceObserver = null; } /** * 开始监控 */ start() { if (this.monitoringActive) return; this.monitoringActive = true; // 启动性能观察器 if (typeof PerformanceObserver !== 'undefined') { this.performanceObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); entries.forEach(entry => { this._recordPerformanceEntry(entry); }); }); try { this.performanceObserver.observe({ entryTypes: ['measure', 'navigation', 'paint'] }); } catch (error) { console.warn('⚠️ 性能观察器不支持某些观察类型:', error.message); } } // 启动内存监控 this._startMemoryMonitoring(); console.log('📊 性能监控已启动'); } /** * 停止监控 */ stop() { this.monitoringActive = false; if (this.performanceObserver) { this.performanceObserver.disconnect(); this.performanceObserver = null; } console.log('📊 性能监控已停止'); } /** * 记录性能条目 * @param {PerformanceEntry} entry - 性能条目 */ _recordPerformanceEntry(entry) { if (!this.monitoringActive) return; const key = `${entry.name}-${entry.entryType}`; const currentMetrics = this.metrics.get(key) || { count: 0, total: 0, average: 0, min: Infinity, max: 0, samples: [] }; currentMetrics.count++; if (entry.duration) { currentMetrics.total += entry.duration; currentMetrics.average = currentMetrics.total / currentMetrics.count; currentMetrics.min = Math.min(currentMetrics.min, entry.duration); currentMetrics.max = Math.max(currentMetrics.max, entry.duration); currentMetrics.samples.push(entry.duration); // 限制样本数量 if (currentMetrics.samples.length > 100) { currentMetrics.samples.shift(); } } this.metrics.set(key, currentMetrics); } /** * 启动内存监控 */ _startMemoryMonitoring() { setInterval(() => { if (!this.monitoringActive) return; // 获取内存信息(如果支持) if (performance.memory) { const memoryInfo = { used: performance.memory.usedJSHeapSize, total: performance.memory.totalJSHeapSize, limit: performance.memory.jsHeapSizeLimit, timestamp: Date.now() }; this.memorySamples.push(memoryInfo); // 限制样本数量 if (this.memorySamples.length > 100) { this.memorySamples.shift(); } // 检查内存阈值 if (memoryInfo.used > TEST_CONFIG.performanceThresholds.memoryUsage) { this._createAlert('memory_threshold', '内存使用量超过阈值', { current: memoryInfo.used, threshold: TEST_CONFIG.performanceThresholds.memoryUsage }); } } }, 5000); // 每5秒检查一次 } /** * 创建告警 * @param {string} type - 告警类型 * @param {string} message - 告警消息 * @param {Object} data - 告警数据 */ _createAlert(type, message, data) { const alert = { id: `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, type, message, data, timestamp: Date.now(), acknowledged: false }; this.alerts.push(alert); // 限制告警数量 if (this.alerts.length > 50) { this.alerts.shift(); } console.warn(`🚨 性能告警 [${type}]: ${message}`, data); } /** * 获取性能摘要 * @returns {Object} 性能摘要 */ getPerformanceSummary() { const summary = { metrics: Object.fromEntries(this.metrics), memory: { current: this.memorySamples.length > 0 ? this.memorySamples[this.memorySamples.length - 1] : null, samples: this.memorySamples.length, trend: this._calculateMemoryTrend() }, alerts: { total: this.alerts.length, unacknowledged: this.alerts.filter(a => !a.acknowledged).length, recent: this.alerts.slice(-10) }, monitoring: { active: this.monitoringActive, uptime: Date.now() - (this.startTime || Date.now()) } }; return summary; } /** * 计算内存趋势 * @returns {Object} 内存趋势 */ _calculateMemoryTrend() { if (this.memorySamples.length < 2) return { direction: 'unknown', change: 0 }; const recent = this.memorySamples.slice(-10); const first = recent[0]; const last = recent[recent.length - 1]; const change = last.used - first.used; const direction = change > 1024 * 1024 ? 'increasing' : change < -1024 * 1024 ? 'decreasing' : 'stable'; return { direction, change, changeMB: change / (1024 * 1024), period: last.timestamp - first.timestamp }; } /** * 确认告警 * @param {string} alertId - 告警ID */ acknowledgeAlert(alertId) { const alert = this.alerts.find(a => a.id === alertId); if (alert) { alert.acknowledged = true; } } /** * 清除告警 * @param {string} alertId - 告警ID */ clearAlert(alertId) { const index = this.alerts.findIndex(a => a.id === alertId); if (index > -1) { this.alerts.splice(index, 1); } } /** * 清除所有告警 */ clearAllAlerts() { this.alerts = []; } } // 集成测试器主类 class IntegrationTester { constructor() { this.testResults = new Map(); this.performanceMonitor = new PerformanceMonitor(); this.isRunning = false; this.testSuites = new Map(); this._initializeTestSuites(); } /** * 初始化测试套件 */ _initializeTestSuites() { // Panel测试套件 this.testSuites.set('panel', { name: 'Panel组件测试套件', tests: Object.keys(TEST_CONFIG.testCases.panel) }); // TabPage测试套件 this.testSuites.set('tabpage', { name: 'TabPage组件测试套件', tests: Object.keys(TEST_CONFIG.testCases.tabpage) }); // Area测试套件 this.testSuites.set('area', { name: 'Area组件测试套件', tests: Object.keys(TEST_CONFIG.testCases.area) }); // 拖拽测试套件 this.testSuites.set('drag', { name: '拖拽功能测试套件', tests: Object.keys(TEST_CONFIG.testCases.drag) }); // 集成测试套件 this.testSuites.set('integration', { name: '集成测试套件', tests: Object.keys(TEST_CONFIG.testCases.integration) }); } /** * 运行所有测试 * @param {Array} suiteNames - 要运行的测试套件名称 * @returns {Promise} 测试结果 */ async runAllTests(suiteNames = null) { if (this.isRunning) { throw new Error('测试已在运行中'); } this.isRunning = true; console.log('🚀 开始运行集成测试...'); // 启动性能监控 this.performanceMonitor.start(); try { const results = {}; const suitesToRun = suiteNames || Array.from(this.testSuites.keys()); for (const suiteName of suitesToRun) { console.log(`\n📋 运行测试套件: ${suiteName}`); results[suiteName] = await this._runTestSuite(suiteName); } // 生成测试报告 const report = this._generateTestReport(results); // 显示结果 this._displayTestResults(report); return report; } catch (error) { console.error('❌ 测试执行失败:', error); throw error; } finally { this.isRunning = false; this.performanceMonitor.stop(); } } /** * 运行单个测试套件 * @param {string} suiteName - 测试套件名称 * @returns {Promise} 测试结果 */ async _runTestSuite(suiteName) { const suite = this.testSuites.get(suiteName); if (!suite) { throw new Error(`未知测试套件: ${suiteName}`); } const suiteResults = []; for (const testName of suite.tests) { console.log(` 🧪 运行测试: ${testName}`); const result = await this._runSingleTest(suiteName, testName); suiteResults.push(result); } return suiteResults; } /** * 运行单个测试 * @param {string} suiteName - 测试套件名称 * @param {string} testName - 测试名称 * @returns {Promise} 测试结果 */ async _runSingleTest(suiteName, testName) { const testConfig = TEST_CONFIG.testCases[suiteName][testName]; const result = new TestResult(testName, suiteName); try { // 记录开始时间 result.startTime = Date.now(); // 根据测试类型执行相应测试 switch (suiteName) { case 'panel': await this._runPanelTest(testName, testConfig, result); break; case 'tabpage': await this._runTabPageTest(testName, testConfig, result); break; case 'area': await this._runAreaTest(testName, testConfig, result); break; case 'drag': await this._runDragTest(testName, testConfig, result); break; case 'integration': await this._runIntegrationTest(testName, testConfig, result); break; } // 完成测试 result.complete('passed'); } catch (error) { result.complete('failed', error); console.error(`❌ 测试失败 [${suiteName}.${testName}]:`, error.message); } this.testResults.set(`${suiteName}.${testName}`, result); return result; } /** * 运行Panel测试 * @param {string} testName - 测试名称 * @param {Object} config - 测试配置 * @param {TestResult} result - 测试结果 */ async _runPanelTest(testName, config, result) { switch (testName) { case 'createPanel': await this._testCreatePanel(result); break; case 'destroyPanel': await this._testDestroyPanel(result); break; case 'maximizePanel': await this._testMaximizePanel(result); break; case 'minimizePanel': await this._testMinimizePanel(result); break; case 'restorePanel': await this._testRestorePanel(result); break; case 'closePanel': await this._testClosePanel(result); break; } } /** * 运行TabPage测试 * @param {string} testName - 测试名称 * @param {Object} config - 测试配置 * @param {TestResult} result - 测试结果 */ async _runTabPageTest(testName, config, result) { switch (testName) { case 'createTabPage': await this._testCreateTabPage(result); break; case 'destroyTabPage': await this._testDestroyTabPage(result); break; case 'switchTabPage': await this._testSwitchTabPage(result); break; case 'closeTabPage': await this._testCloseTabPage(result); break; case 'moveTabPage': await this._testMoveTabPage(result); break; } } /** * 运行Area测试 * @param {string} testName - 测试名称 * @param {Object} config - 测试配置 * @param {TestResult} result - 测试结果 */ async _runAreaTest(testName, config, result) { switch (testName) { case 'createArea': await this._testCreateArea(result); break; case 'destroyArea': await this._testDestroyArea(result); break; case 'dockArea': await this._testDockArea(result); break; case 'mergeArea': await this._testMergeArea(result); break; case 'splitArea': await this._testSplitArea(result); break; } } /** * 运行拖拽测试 * @param {string} testName - 测试名称 * @param {Object} config - 测试配置 * @param {TestResult} result - 测试结果 */ async _runDragTest(testName, config, result) { switch (testName) { case 'panelDrag': await this._testPanelDrag(result); break; case 'tabpageDrag': await this._testTabPageDrag(result); break; case 'areaDrag': await this._testAreaDrag(result); break; case 'multiDrag': await this._testMultiDrag(result); break; } } /** * 运行集成测试 * @param {string} testName - 测试名称 * @param {Object} config - 测试配置 * @param {TestResult} result - 测试结果 */ async _runIntegrationTest(testName, config, result) { switch (testName) { case 'panelTabpage': await this._testPanelTabPageIntegration(result); break; case 'areaPanel': await this._testAreaPanelIntegration(result); break; case 'crossComponent': await this._testCrossComponentIntegration(result); break; case 'concurrentEvents': await this._testConcurrentEvents(result); break; } } /** * 测试创建Panel * @param {TestResult} result - 测试结果 */ async _testCreatePanel(result) { const startTime = performance.now(); // 模拟Panel创建事件 eventBus.emit(PANEL_EVENT_TYPES.PANEL_CREATE_REQUEST, { panelId: `test-panel-${Date.now()}`, title: '测试Panel', content: '测试内容' }); // 等待处理完成 await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); // 添加断言 result.addAssertion(true, 'Panel创建事件应被正确处理', true, true); } /** * 测试销毁Panel * @param {TestResult} result - 测试结果 */ async _testDestroyPanel(result) { const startTime = performance.now(); eventBus.emit(PANEL_EVENT_TYPES.PANEL_DESTROY_REQUEST, { panelId: 'test-panel-destroy' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel销毁事件应被正确处理', true, true); } /** * 测试最大化Panel * @param {TestResult} result - 测试结果 */ async _testMaximizePanel(result) { const startTime = performance.now(); eventBus.emit(PANEL_EVENT_TYPES.PANEL_MAXIMIZE, { panelId: 'test-panel-maximize' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel最大化事件应被正确处理', true, true); } /** * 测试最小化Panel * @param {TestResult} result - 测试结果 */ async _testMinimizePanel(result) { const startTime = performance.now(); eventBus.emit(PANEL_EVENT_TYPES.PANEL_MINIMIZE, { panelId: 'test-panel-minimize' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel最小化事件应被正确处理', true, true); } /** * 测试还原Panel * @param {TestResult} result - 测试结果 */ async _testRestorePanel(result) { const startTime = performance.now(); eventBus.emit(PANEL_EVENT_TYPES.PANEL_RESTORE, { panelId: 'test-panel-restore' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel还原事件应被正确处理', true, true); } /** * 测试关闭Panel * @param {TestResult} result - 测试结果 */ async _testClosePanel(result) { const startTime = performance.now(); eventBus.emit(PANEL_EVENT_TYPES.PANEL_CLOSE_REQUEST, { panelId: 'test-panel-close' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel关闭事件应被正确处理', true, true); } /** * 测试创建TabPage * @param {TestResult} result - 测试结果 */ async _testCreateTabPage(result) { const startTime = performance.now(); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_CREATE_REQUEST, { tabPageId: `test-tabpage-${Date.now()}`, title: '测试TabPage', content: '测试内容' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage创建事件应被正确处理', true, true); } /** * 测试销毁TabPage * @param {TestResult} result - 测试结果 */ async _testDestroyTabPage(result) { const startTime = performance.now(); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_DESTROY_REQUEST, { tabPageId: 'test-tabpage-destroy' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage销毁事件应被正确处理', true, true); } /** * 测试切换TabPage * @param {TestResult} result - 测试结果 */ async _testSwitchTabPage(result) { const startTime = performance.now(); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_SWITCH, { tabPageId: 'test-tabpage-switch', targetIndex: 1 }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage切换事件应被正确处理', true, true); } /** * 测试关闭TabPage * @param {TestResult} result - 测试结果 */ async _testCloseTabPage(result) { const startTime = performance.now(); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_CLOSE_REQUEST, { tabPageId: 'test-tabpage-close' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage关闭事件应被正确处理', true, true); } /** * 测试移动TabPage * @param {TestResult} result - 测试结果 */ async _testMoveTabPage(result) { const startTime = performance.now(); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_MOVE, { tabPageId: 'test-tabpage-move', targetPosition: { x: 100, y: 200 } }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage移动事件应被正确处理', true, true); } /** * 测试创建Area * @param {TestResult} result - 测试结果 */ async _testCreateArea(result) { const startTime = performance.now(); eventBus.emit(AREA_EVENT_TYPES.AREA_CREATE_REQUEST, { areaId: `test-area-${Date.now()}`, type: 'dockable' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area创建事件应被正确处理', true, true); } /** * 测试销毁Area * @param {TestResult} result - 测试结果 */ async _testDestroyArea(result) { const startTime = performance.now(); eventBus.emit(AREA_EVENT_TYPES.AREA_DESTROY_REQUEST, { areaId: 'test-area-destroy' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area销毁事件应被正确处理', true, true); } /** * 测试停靠Area * @param {TestResult} result - 测试结果 */ async _testDockArea(result) { const startTime = performance.now(); eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, { areaId: 'test-area-dock', targetAreaId: 'target-area' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area停靠事件应被正确处理', true, true); } /** * 测试合并Area * @param {TestResult} result - 测试结果 */ async _testMergeArea(result) { const startTime = performance.now(); eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, { sourceAreaId: 'source-area', targetAreaId: 'target-area', mergeType: 'horizontal' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area合并事件应被正确处理', true, true); } /** * 测试分割Area * @param {TestResult} result - 测试结果 */ async _testSplitArea(result) { const startTime = performance.now(); eventBus.emit(AREA_EVENT_TYPES.AREA_SPLIT, { areaId: 'test-area-split', splitType: 'vertical', splitRatio: 0.5 }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area分割事件应被正确处理', true, true); } /** * 测试Panel拖拽 * @param {TestResult} result - 测试结果 */ async _testPanelDrag(result) { const startTime = performance.now(); // 模拟拖拽开始 eventBus.emit('panel.drag.start', { dragId: 'test-panel-drag', panelId: 'test-panel-drag-id', startPosition: { x: 100, y: 100 } }); // 模拟拖拽移动 for (let i = 0; i < 10; i++) { eventBus.emit('panel.drag.move', { dragId: 'test-panel-drag', currentPosition: { x: 100 + i * 10, y: 100 + i * 5 } }); await new Promise(resolve => setTimeout(resolve, 16)); // 模拟60fps } // 模拟拖拽结束 eventBus.emit('panel.drag.end', { dragId: 'test-panel-drag', finalPosition: { x: 200, y: 150 }, success: true }); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel拖拽事件应被正确处理', true, true); } /** * 测试TabPage拖拽 * @param {TestResult} result - 测试结果 */ async _testTabPageDrag(result) { const startTime = performance.now(); eventBus.emit('tabpage.drag.start', { dragId: 'test-tabpage-drag', tabPageId: 'test-tabpage-drag-id', startPosition: { x: 50, y: 50 } }); eventBus.emit('tabpage.drag.move', { dragId: 'test-tabpage-drag', currentPosition: { x: 150, y: 100 } }); eventBus.emit('tabpage.drag.end', { dragId: 'test-tabpage-drag', finalPosition: { x: 150, y: 100 }, success: true }); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'TabPage拖拽事件应被正确处理', true, true); } /** * 测试Area拖拽 * @param {TestResult} result - 测试结果 */ async _testAreaDrag(result) { const startTime = performance.now(); eventBus.emit('area.drag.start', { dragId: 'test-area-drag', areaId: 'test-area-drag-id', startPosition: { x: 200, y: 200 } }); eventBus.emit('area.drag.move', { dragId: 'test-area-drag', currentPosition: { x: 300, y: 250 } }); eventBus.emit('area.drag.end', { dragId: 'test-area-drag', finalPosition: { x: 300, y: 250 }, success: true }); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area拖拽事件应被正确处理', true, true); } /** * 测试多拖拽 * @param {TestResult} result - 测试结果 */ async _testMultiDrag(result) { const startTime = performance.now(); const dragIds = ['test-multi-drag-1', 'test-multi-drag-2', 'test-multi-drag-3']; // 同时启动多个拖拽 dragIds.forEach((dragId, index) => { eventBus.emit('panel.drag.start', { dragId, panelId: `panel-${index}`, startPosition: { x: 50 + index * 100, y: 50 } }); }); // 模拟同时移动 for (let i = 0; i < 5; i++) { dragIds.forEach((dragId, index) => { eventBus.emit('panel.drag.move', { dragId, currentPosition: { x: 50 + index * 100 + i * 20, y: 50 + i * 10 } }); }); await new Promise(resolve => setTimeout(resolve, 33)); // 模拟30fps } // 结束所有拖拽 dragIds.forEach((dragId, index) => { eventBus.emit('panel.drag.end', { dragId, finalPosition: { x: 50 + index * 100 + 100, y: 50 + 50 }, success: true }); }); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, '多拖拽事件应被正确处理', true, true); } /** * 测试Panel和TabPage集成 * @param {TestResult} result - 测试结果 */ async _testPanelTabPageIntegration(result) { const startTime = performance.now(); // 创建Panel,然后在其中创建TabPage eventBus.emit(PANEL_EVENT_TYPES.PANEL_CREATE_REQUEST, { panelId: 'integration-panel', title: '集成测试Panel', content: '包含TabPage的Panel' }); await new Promise(resolve => setTimeout(resolve, 100)); eventBus.emit(TABPAGE_EVENT_TYPES.TABPAGE_CREATE_REQUEST, { tabPageId: 'integration-tabpage', title: '集成测试TabPage', parentPanelId: 'integration-panel' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Panel和TabPage集成应正确工作', true, true); } /** * 测试Area和Panel集成 * @param {TestResult} result - 测试结果 */ async _testAreaPanelIntegration(result) { const startTime = performance.now(); // 创建Area,然后在其中创建Panel eventBus.emit(AREA_EVENT_TYPES.AREA_CREATE_REQUEST, { areaId: 'integration-area', type: 'container' }); await new Promise(resolve => setTimeout(resolve, 100)); eventBus.emit(PANEL_EVENT_TYPES.PANEL_CREATE_REQUEST, { panelId: 'integration-area-panel', title: 'Area中的Panel', parentAreaId: 'integration-area' }); await new Promise(resolve => setTimeout(resolve, 100)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, 'Area和Panel集成应正确工作', true, true); } /** * 测试跨组件通信 * @param {TestResult} result - 测试结果 */ async _testCrossComponentIntegration(result) { const startTime = performance.now(); // 发送跨组件请求 eventBus.emit(GLOBAL_EVENT_TYPES.CROSS_COMPONENT_REQUEST, { requestId: 'test-request', targetComponent: 'panel', action: 'createPanel', payload: { title: '跨组件创建的Panel' } }); await new Promise(resolve => setTimeout(resolve, 200)); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, '跨组件通信应正确工作', true, true); } /** * 测试并发事件 * @param {TestResult} result - 测试结果 */ async _testConcurrentEvents(result) { const startTime = performance.now(); const promises = []; // 并发发送多个事件 for (let i = 0; i < 20; i++) { promises.push(Promise.resolve().then(() => { eventBus.emit(PANEL_EVENT_TYPES.PANEL_CREATE_REQUEST, { panelId: `concurrent-panel-${i}`, title: `并发Panel ${i}` }); })); } await Promise.all(promises); const handleTime = performance.now() - startTime; result.recordHandle(true, handleTime); result.addAssertion(true, '并发事件应被正确处理', true, true); } /** * 生成测试报告 * @param {Object} results - 测试结果 * @returns {Object} 测试报告 */ _generateTestReport(results) { const allResults = Object.values(results).flat(); const performanceSummary = this.performanceMonitor.getPerformanceSummary(); const report = { timestamp: new Date().toISOString(), summary: { total: allResults.length, passed: allResults.filter(r => r.status === 'passed').length, failed: allResults.filter(r => r.status === 'failed').length, timeout: allResults.filter(r => r.status === 'timeout').length, successRate: allResults.length > 0 ? (allResults.filter(r => r.status === 'passed').length / allResults.length * 100).toFixed(2) : 0 }, performance: performanceSummary, suites: {}, issues: [], recommendations: [] }; // 为每个套件生成报告 for (const [suiteName, suiteResults] of Object.entries(results)) { const passed = suiteResults.filter(r => r.status === 'passed').length; const total = suiteResults.length; report.suites[suiteName] = { name: this.testSuites.get(suiteName)?.name || suiteName, total, passed, failed: total - passed, successRate: total > 0 ? (passed / total * 100).toFixed(2) : 0, averageDuration: suiteResults.reduce((sum, r) => sum + r.duration, 0) / total || 0, results: suiteResults.map(r => r.getSummary()) }; } // 分析问题和建议 this._analyzeIssuesAndRecommendations(report, allResults, performanceSummary); return report; } /** * 分析问题和建议 * @param {Object} report - 报告对象 * @param {Array} results - 测试结果 * @param {Object} performanceSummary - 性能摘要 */ _analyzeIssuesAndRecommendations(report, results, performanceSummary) { // 检查失败的测试 const failedTests = results.filter(r => r.status === 'failed'); if (failedTests.length > 0) { report.issues.push({ type: 'test_failures', severity: 'high', message: `${failedTests.length} 个测试失败`, details: failedTests.map(r => ({ test: `${r.testType}.${r.testName}`, error: r.error?.message || '未知错误', duration: r.duration })) }); } // 检查性能问题 const slowTests = results.filter(r => r.duration > 5000); if (slowTests.length > 0) { report.issues.push({ type: 'slow_tests', severity: 'medium', message: `${slowTests.length} 个测试执行时间过长`, details: slowTests.map(r => ({ test: `${r.testType}.${r.testName}`, duration: r.duration, threshold: 5000 })) }); } // 检查内存使用 if (performanceSummary.memory.current && performanceSummary.memory.current.used > TEST_CONFIG.performanceThresholds.memoryUsage) { report.issues.push({ type: 'high_memory_usage', severity: 'medium', message: '内存使用量超过阈值', details: { current: performanceSummary.memory.current.used, threshold: TEST_CONFIG.performanceThresholds.memoryUsage, usage: (performanceSummary.memory.current.used / (1024 * 1024)).toFixed(2) + 'MB' } }); } // 生成建议 if (failedTests.length > 0) { report.recommendations.push({ type: 'fix_failures', priority: 'high', message: '修复失败的测试用例', actions: [ '检查错误日志以确定失败原因', '修复相应的处理器实现', '重新运行测试确保修复生效' ] }); } if (performanceSummary.alerts.unacknowledged > 0) { report.recommendations.push({ type: 'resolve_performance_alerts', priority: 'medium', message: '解决性能告警', actions: [ '检查未确认的性能告警', '优化性能瓶颈代码', '调整性能阈值设置' ] }); } if (slowTests.length > 0) { report.recommendations.push({ type: 'optimize_slow_tests', priority: 'medium', message: '优化执行缓慢的测试', actions: [ '分析长时间运行的测试用例', '优化事件处理逻辑', '考虑使用异步处理减少阻塞' ] }); } } /** * 显示测试结果 * @param {Object} report - 测试报告 */ _displayTestResults(report) { console.log('\n' + '='.repeat(80)); console.log('🧪 集成测试报告'); console.log('='.repeat(80)); // 总体摘要 console.log('\n📊 总体摘要:'); console.log(` 总测试数: ${report.summary.total}`); console.log(` 通过: ${report.summary.passed}`); console.log(` 失败: ${report.summary.failed}`); console.log(` 超时: ${report.summary.timeout}`); console.log(` 成功率: ${report.summary.successRate}%`); // 测试套件结果 console.log('\n📋 测试套件结果:'); for (const [suiteKey, suite] of Object.entries(report.suites)) { console.log(`\n ${suite.name}:`); console.log(` 总数: ${suite.total} | 通过: ${suite.passed} | 失败: ${suite.failed} | 成功率: ${suite.successRate}%`); console.log(` 平均执行时间: ${suite.averageDuration.toFixed(2)}ms`); // 显示失败的测试 const failedTests = suite.results.filter(r => r.status === 'failed'); if (failedTests.length > 0) { console.log(` ❌ 失败的测试:`); failedTests.forEach(test => { console.log(` - ${test.testName} (${test.error || '未知错误'})`); }); } } // 性能摘要 console.log('\n⚡ 性能摘要:'); if (report.performance.memory.current) { console.log(` 当前内存使用: ${(report.performance.memory.current.used / (1024 * 1024)).toFixed(2)}MB / ${(report.performance.memory.current.total / (1024 * 1024)).toFixed(2)}MB`); } console.log(` 性能告警: ${report.performance.alerts.unacknowledged} 个未确认`); // 问题和建议 if (report.issues.length > 0) { console.log('\n⚠️ 发现的问题:'); report.issues.forEach(issue => { console.log(` [${issue.severity.toUpperCase()}] ${issue.message}`); }); } if (report.recommendations.length > 0) { console.log('\n💡 建议:'); report.recommendations.forEach((rec, index) => { console.log(` ${index + 1}. [${rec.priority.toUpperCase()}] ${rec.message}`); rec.actions.forEach(action => { console.log(` - ${action}`); }); }); } console.log('\n' + '='.repeat(80)); } /** * 获取测试结果 * @returns {Map} 测试结果映射 */ getTestResults() { return new Map(this.testResults); } /** * 获取性能摘要 * @returns {Object} 性能摘要 */ getPerformanceSummary() { return this.performanceMonitor.getPerformanceSummary(); } /** * 清除测试结果 */ clearResults() { this.testResults.clear(); this.performanceMonitor.clearAllAlerts(); } /** * 销毁测试器 */ destroy() { this.stop(); this.clearResults(); console.log('🗑️ 集成测试器已销毁'); } } // 创建单例实例 const integrationTester = new IntegrationTester(); // 便捷API export const testActions = { /** * 运行所有测试 * @param {Array} suites - 测试套件列表 * @returns {Promise} 测试报告 */ runAll: (suites = null) => integrationTester.runAllTests(suites), /** * 获取测试结果 * @returns {Map} 测试结果 */ getResults: () => integrationTester.getTestResults(), /** * 获取性能摘要 * @returns {Object} 性能摘要 */ getPerformanceSummary: () => integrationTester.getPerformanceSummary(), /** * 清除测试结果 */ clearResults: () => integrationTester.clearResults() }; // 导出 export default integrationTester; export { TEST_CONFIG, TestResult, PerformanceMonitor, testActions };