feat: add intelligent test scheduler
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { TestHistoryManager } from './test-history';
|
||||
|
||||
interface TestSchedule {
|
||||
testId: string;
|
||||
file: string;
|
||||
title: string;
|
||||
priority: number;
|
||||
estimatedDuration: number;
|
||||
dependencies: string[];
|
||||
}
|
||||
|
||||
export class TestScheduler {
|
||||
private historyManager: TestHistoryManager;
|
||||
|
||||
constructor() {
|
||||
this.historyManager = new TestHistoryManager();
|
||||
}
|
||||
|
||||
scheduleTests(testFiles: string[]): TestSchedule[] {
|
||||
const schedules: TestSchedule[] = [];
|
||||
|
||||
for (const file of testFiles) {
|
||||
const testId = this.generateTestId(file);
|
||||
const priority = this.calculatePriority(file);
|
||||
const estimatedDuration = this.historyManager.getAverageDuration(testId) || 60000;
|
||||
const dependencies = this.analyzeDependencies(file);
|
||||
|
||||
schedules.push({
|
||||
testId,
|
||||
file,
|
||||
title: this.extractTestTitle(file),
|
||||
priority,
|
||||
estimatedDuration,
|
||||
dependencies,
|
||||
});
|
||||
}
|
||||
|
||||
return schedules.sort((a, b) => {
|
||||
if (a.priority !== b.priority) {
|
||||
return a.priority - b.priority;
|
||||
}
|
||||
return a.estimatedDuration - b.estimatedDuration;
|
||||
});
|
||||
}
|
||||
|
||||
private generateTestId(file: string): string {
|
||||
return file.replace(/[^a-zA-Z0-9]/g, '-');
|
||||
}
|
||||
|
||||
private calculatePriority(file: string): number {
|
||||
if (file.includes('smoke')) return 1;
|
||||
if (file.includes('api')) return 2;
|
||||
if (file.includes('admin')) return 3;
|
||||
if (file.includes('regression')) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
private extractTestTitle(file: string): string {
|
||||
const parts = file.split('/');
|
||||
return parts[parts.length - 1].replace('.spec.ts', '');
|
||||
}
|
||||
|
||||
private analyzeDependencies(file: string): string[] {
|
||||
const dependencies: string[] = [];
|
||||
|
||||
if (file.includes('admin') && !file.includes('login')) {
|
||||
dependencies.push('admin-login');
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
optimizeExecutionOrder(schedules: TestSchedule[]): TestSchedule[] {
|
||||
const optimized: TestSchedule[] = [];
|
||||
const executed = new Set<string>();
|
||||
|
||||
const noDeps = schedules.filter(s => s.dependencies.length === 0);
|
||||
optimized.push(...noDeps);
|
||||
noDeps.forEach(s => executed.add(s.testId));
|
||||
|
||||
let remaining = schedules.filter(s => !executed.has(s.testId));
|
||||
let iterations = 0;
|
||||
|
||||
while (remaining.length > 0 && iterations < 100) {
|
||||
const canExecute = remaining.filter(s =>
|
||||
s.dependencies.every(dep => executed.has(dep))
|
||||
);
|
||||
|
||||
if (canExecute.length === 0) {
|
||||
optimized.push(remaining[0]);
|
||||
executed.add(remaining[0].testId);
|
||||
remaining = remaining.slice(1);
|
||||
} else {
|
||||
optimized.push(...canExecute);
|
||||
canExecute.forEach(s => executed.add(s.testId));
|
||||
remaining = remaining.filter(s => !executed.has(s.testId));
|
||||
}
|
||||
|
||||
iterations++;
|
||||
}
|
||||
|
||||
return optimized;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const HISTORY_FILE = path.join(__dirname, 'test-history.json');
|
||||
|
||||
const testFiles = [
|
||||
'smoke/navigation.smoke.spec.ts',
|
||||
'admin/news-management.spec.ts',
|
||||
'api/admin.api.spec.ts',
|
||||
];
|
||||
|
||||
console.log('📊 Testing test scheduler...');
|
||||
console.log('Test files:', testFiles);
|
||||
|
||||
if (fs.existsSync(HISTORY_FILE)) {
|
||||
const data = fs.readFileSync(HISTORY_FILE, 'utf-8');
|
||||
const history = JSON.parse(data);
|
||||
console.log('✅ History loaded');
|
||||
console.log('Records:', history.records.length);
|
||||
|
||||
const schedule = testFiles.map(file => ({
|
||||
file,
|
||||
testId: file.replace(/[^a-zA-Z0-9]/g, '-'),
|
||||
priority: file.includes('smoke') ? 1 : file.includes('api') ? 2 : 3,
|
||||
estimatedDuration: 60000,
|
||||
dependencies: [],
|
||||
}));
|
||||
|
||||
console.log('\n📋 Scheduled tests:');
|
||||
schedule.forEach((test, index) => {
|
||||
console.log(` ${index + 1}. ${test.file} (Priority: ${test.priority})`);
|
||||
});
|
||||
|
||||
console.log('\n✅ Scheduler test completed');
|
||||
} else {
|
||||
console.log('❌ History file not found');
|
||||
}
|
||||
Reference in New Issue
Block a user