import { logger } from './utils/logger'; import { TestEnvironmentManager } from './core/environment'; import { TestExecutor } from './core/test-executor'; import { TDDIterator } from './core/tdd-iterator'; import { ReportGenerator } from './core/report-generator'; import { TestResult, TestStatus } from './models/test-result'; interface RunOptions { modules?: Array<'api' | 'admin' | 'uniapp'>; startServices?: boolean; tddEnabled?: boolean; maxIterations?: number; reportFormats?: Array<'html' | 'json' | 'junit' | 'markdown'>; exitOnComplete?: boolean; } class RunAllTests { private environment: TestEnvironmentManager; private executor: TestExecutor; private tddIterator: TDDIterator; private reportGenerator: ReportGenerator; constructor() { this.environment = new TestEnvironmentManager(); this.executor = new TestExecutor(); this.tddIterator = new TDDIterator({ maxIterations: 3, autoFixEnabled: true, stopOnCriticalFailure: true }); this.reportGenerator = new ReportGenerator({ formats: ['html', 'json', 'markdown'] }); } async run(options: RunOptions = {}): Promise { const startTime = Date.now(); logger.section('E2E 全量自动化测试'); logger.info('测试启动', { options }); try { if (options.startServices !== false) { await this.startServices(options.modules); } logger.section('执行测试'); const initialResult = await this.executor.executeAll(); let finalResult = initialResult; if (options.tddEnabled !== false && initialResult.failedTests > 0) { logger.section('TDD 迭代优化'); finalResult = await this.tddIterator.iterate(initialResult); } logger.section('生成报告'); const iterations = this.tddIterator.getIterations(); const reportFiles = await this.reportGenerator.generate(finalResult, iterations); logger.info('报告生成完成', { files: reportFiles }); this.printSummary(finalResult, startTime); const exitCode = finalResult.failedTests > 0 ? 1 : 0; if (options.exitOnComplete !== false) { await this.cleanup(); } return exitCode; } catch (error) { logger.error('测试执行失败', error); await this.cleanup(); return 1; } } private async startServices(modules?: Array<'api' | 'admin' | 'uniapp'>): Promise { logger.section('启动服务'); const servicesToStart = modules || ['api', 'admin', 'uniapp']; for (const service of servicesToStart) { switch (service) { case 'api': await this.environment.startAPIService(); break; case 'admin': await this.environment.startAdminService(); break; case 'uniapp': await this.environment.startUniappService(); break; } } await this.waitForServicesReady(servicesToStart); } private async waitForServicesReady(services: Array<'api' | 'admin' | 'uniapp'>): Promise { logger.info('等待服务就绪...'); const healthChecks: Record = { api: process.env.API_BASE_URL || 'http://localhost:8080/actuator/health', admin: process.env.ADMIN_BASE_URL || 'http://localhost:5174', uniapp: process.env.UNIAPP_BASE_URL || 'http://localhost:8081' }; for (const service of services) { const url = healthChecks[service]; if (url) { let retries = 30; while (retries > 0) { const isReady = await this.environment.checkServiceHealth(service, url); if (isReady) { logger.info(`${service} 服务就绪`); break; } retries--; await this.sleep(2000); } if (retries === 0) { logger.warn(`${service} 服务未能在预期时间内就绪`); } } } } private printSummary(result: TestResult, startTime: number): void { const totalDuration = Date.now() - startTime; logger.section('测试执行总结'); console.log('\n' + '='.repeat(60)); console.log(' 测试执行完成'); console.log('='.repeat(60)); console.log(`\n 总测试数: ${result.totalTests}`); console.log(` ✅ 通过: ${result.passedTests}`); console.log(` ❌ 失败: ${result.failedTests}`); console.log(` ⏭️ 跳过: ${result.skippedTests}`); console.log(`\n 通过率: ${result.passRate.toFixed(2)}%`); console.log(` 总耗时: ${(totalDuration / 1000).toFixed(2)} 秒`); console.log('\n' + '='.repeat(60) + '\n'); if (result.failedTests > 0) { logger.warn('存在失败的测试用例,请查看详细报告'); } else { logger.info('所有测试通过!'); } } private async cleanup(): Promise { logger.section('清理环境'); await this.environment.cleanup(); logger.info('环境清理完成,准备退出'); } private sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } } async function main(): Promise { const args = process.argv.slice(2); const options: RunOptions = { modules: undefined, startServices: true, tddEnabled: true, maxIterations: 3, reportFormats: ['html', 'json', 'markdown'], exitOnComplete: true }; for (let i = 0; i < args.length; i++) { const arg = args[i]; switch (arg) { case '--modules': case '-m': options.modules = args[++i]?.split(',') as Array<'api' | 'admin' | 'uniapp'>; break; case '--no-services': options.startServices = false; break; case '--no-tdd': options.tddEnabled = false; break; case '--iterations': case '-i': options.maxIterations = parseInt(args[++i], 10); break; case '--formats': case '-f': options.reportFormats = args[++i]?.split(',') as Array<'html' | 'json' | 'junit' | 'markdown'>; break; case '--help': case '-h': printHelp(); return 0; } } const runner = new RunAllTests(); return runner.run(options); } function printHelp(): void { console.log(` E2E 全量自动化测试运行器 用法: npx ts-node scripts/run-all-tests.ts [选项] 选项: -m, --modules 指定测试模块 (api,admin,uniapp),默认全部 --no-services 不启动服务(服务已运行时使用) --no-tdd 禁用 TDD 迭代 -i, --iterations TDD 最大迭代次数,默认 3 -f, --formats 报告格式 (html,json,junit,markdown),默认 html,json,markdown -h, --help 显示帮助信息 示例: # 运行所有测试 npx ts-node scripts/run-all-tests.ts # 只运行 API 和 Admin 测试 npx ts-node scripts/run-all-tests.ts --modules api,admin # 服务已运行,只执行测试 npx ts-node scripts/run-all-tests.ts --no-services # 禁用 TDD 迭代 npx ts-node scripts/run-all-tests.ts --no-tdd `); } main() .then(exitCode => { process.exit(exitCode); }) .catch(error => { console.error('执行出错:', error); process.exit(1); }); export { RunAllTests, RunOptions };