Files
everything-is-suitable/everything-is-suitable-test/scripts/run-all-tests.ts
T
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

249 lines
7.1 KiB
TypeScript

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<number> {
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<void> {
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<void> {
logger.info('等待服务就绪...');
const healthChecks: Record<string, string> = {
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<void> {
logger.section('清理环境');
await this.environment.cleanup();
logger.info('环境清理完成,准备退出');
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
async function main(): Promise<number> {
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 <modules> 指定测试模块 (api,admin,uniapp),默认全部
--no-services 不启动服务(服务已运行时使用)
--no-tdd 禁用 TDD 迭代
-i, --iterations <n> TDD 最大迭代次数,默认 3
-f, --formats <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 };