e2e-test-runner.tsā¢33.2 kB
/**
* End-to-End Test Runner for GEPA System
*
* This orchestrator manages comprehensive integration tests covering:
* - Complete evolution workflows
* - MCP tool integrations
* - Performance benchmarks
* - Memory system validation
* - Concurrent operations
* - Error handling and recovery
*/
import { describe, test, expect } from 'vitest';
// beforeAll, afterAll imported but not used
import type {
PromptCandidate,
StartEvolutionParams,
RecordTrajectoryParams,
EvaluatePromptParams,
ReflectParams,
GetParetoFrontierParams,
SelectOptimalParams,
} from '../../types/gepa';
import { TrajectoryStore } from '../../core/trajectory-store';
import { ParetoFrontier } from '../../core/pareto-frontier';
import { ReflectionEngine } from '../../core/reflection-engine';
import { LLMAdapter } from '../../services/llm-adapter';
import { PromptMutator } from '../../services/prompt-mutator';
import { GEPAMCPServer } from '../../mcp/server';
import { TestScenarios } from './test-scenarios';
import { E2ETestHelpers } from './test-helpers';
import { PerformanceBenchmarks } from './performance-benchmarks';
/**
* E2E Test Configuration
*/
export interface E2ETestConfig {
maxConcurrentTests: number;
defaultTimeout: number;
performanceThresholds: {
evolutionTime: number;
trajectoryRecording: number;
paretoFrontierQuery: number;
memoryOperations: number;
};
retryOptions: {
maxRetries: number;
baseDelay: number;
};
}
/**
* E2E Test Results
*/
export interface E2ETestResults {
totalTests: number;
passedTests: number;
failedTests: number;
skippedTests: number;
executionTime: number;
performanceMetrics: {
avgEvolutionTime: number;
avgTrajectoryRecording: number;
avgParetoQuery: number;
avgMemoryOperation: number;
concurrentOperations: number;
};
memoryUsage: {
peakUsage: number;
averageUsage: number;
leakDetected: boolean;
};
errorSummary: {
criticalErrors: string[];
warnings: string[];
recoveredErrors: string[];
};
}
/**
* Test Environment State
*/
interface TestEnvironment {
mcpServer: GEPAMCPServer;
trajectoryStore: TrajectoryStore;
paretoFrontier: ParetoFrontier;
reflectionEngine: ReflectionEngine;
llmAdapter: LLMAdapter;
promptMutator: PromptMutator;
testHelpers: E2ETestHelpers;
scenarios: TestScenarios;
benchmarks: PerformanceBenchmarks;
tempDir: string;
isInitialized: boolean;
}
/**
* Main E2E Test Runner Class
*/
export class E2ETestRunner {
private config: E2ETestConfig;
private environment: TestEnvironment | null = null;
private testResults: E2ETestResults;
private startTime: number = 0;
constructor(config?: Partial<E2ETestConfig>) {
this.config = {
maxConcurrentTests: 3,
defaultTimeout: 60000,
performanceThresholds: {
evolutionTime: 30000,
trajectoryRecording: 1000,
paretoFrontierQuery: 500,
memoryOperations: 100,
},
retryOptions: {
maxRetries: 3,
baseDelay: 1000,
},
...config,
};
this.testResults = {
totalTests: 0,
passedTests: 0,
failedTests: 0,
skippedTests: 0,
executionTime: 0,
performanceMetrics: {
avgEvolutionTime: 0,
avgTrajectoryRecording: 0,
avgParetoQuery: 0,
avgMemoryOperation: 0,
concurrentOperations: 0,
},
memoryUsage: {
peakUsage: 0,
averageUsage: 0,
leakDetected: false,
},
errorSummary: {
criticalErrors: [],
warnings: [],
recoveredErrors: [],
},
};
}
/**
* Initialize test environment
*/
async initialize(): Promise<void> {
try {
this.startTime = Date.now();
// Create temporary directory for test data
const tempDir = './temp/e2e-tests';
await this.createDirectory(tempDir);
// Initialize core components
const trajectoryStore = new TrajectoryStore({
dataDir: `${tempDir}/trajectories`,
maxFileSize: 5 * 1024 * 1024, // 5MB for tests
archiveAfterDays: 1,
indexingEnabled: true,
compressionEnabled: false, // Disable for faster tests
});
const paretoFrontier = new ParetoFrontier({
maxSize: 50, // Smaller for tests
objectives: [
{
name: 'performance',
direction: 'maximize',
weight: 0.7,
extractor: (candidate: PromptCandidate) => candidate.averageScore,
},
{
name: 'diversity',
direction: 'maximize',
weight: 0.3,
extractor: (candidate: PromptCandidate) => candidate.generation / 10,
},
],
archiveEnabled: true,
samplingStrategy: { name: 'ucb', parameters: { confidence: 1.4 } },
});
const llmAdapter = new LLMAdapter({
maxConcurrentProcesses: 2,
processTimeout: 10000, // Shorter for tests
maxRetries: 2,
retryBaseDelay: 500,
executable: 'echo', // Mock for tests
workingDir: tempDir,
env: { NODE_ENV: 'test' },
});
const reflectionEngine = new ReflectionEngine({
trajectoryStore: {
query: trajectoryStore.query.bind(trajectoryStore),
load: trajectoryStore.load.bind(trajectoryStore),
save: async (trajectory) => {
await trajectoryStore.save(trajectory);
},
},
llmAdapter,
config: {
maxAnalysisDepth: 3,
confidenceThreshold: 0.6,
patternMinFrequency: 2,
batchSize: 5,
enableCaching: true,
cacheTimeout: 300000, // 5 minutes
},
});
const promptMutator = new PromptMutator({
maxMutationsPerGeneration: 20,
mutationRate: 0.2,
crossoverRate: 0.6,
adaptiveWeight: 0.15,
fitnessThreshold: 0.7,
maxPromptLength: 2000,
minPromptLength: 10,
requireRoleDefinition: false, // Relaxed for tests
prohibitedTerms: [],
maxConcurrentMutations: 3,
enableCaching: true,
});
const mcpServer = new GEPAMCPServer();
// Initialize test helpers and scenarios
const testHelpers = new E2ETestHelpers({
tempDir,
timeout: this.config.defaultTimeout,
retryOptions: this.config.retryOptions,
});
const scenarios = new TestScenarios({
trajectoryStore,
paretoFrontier,
reflectionEngine,
llmAdapter,
promptMutator,
});
const benchmarks = new PerformanceBenchmarks({
thresholds: this.config.performanceThresholds,
maxConcurrentTests: this.config.maxConcurrentTests,
});
this.environment = {
mcpServer,
trajectoryStore,
paretoFrontier,
reflectionEngine,
llmAdapter,
promptMutator,
testHelpers,
scenarios,
benchmarks,
tempDir,
isInitialized: true,
};
// eslint-disable-next-line no-console
console.log('ā
E2E test environment initialized successfully');
} catch (error) {
// eslint-disable-next-line no-console
console.error('ā Failed to initialize E2E test environment:', error);
throw error;
}
}
/**
* Run all E2E test suites
*/
async runAllTests(): Promise<E2ETestResults> {
if (!this.environment?.isInitialized) {
throw new Error('Test environment not initialized');
}
try {
// eslint-disable-next-line no-console
console.log('š Starting comprehensive E2E test suite...');
// Test Suite 1: Core Workflow Tests
await this.runCoreWorkflowTests();
// Test Suite 2: MCP Tool Integration Tests
await this.runMCPToolTests();
// Test Suite 3: Performance and Load Tests
await this.runPerformanceTests();
// Test Suite 4: Memory System Tests
await this.runMemorySystemTests();
// Test Suite 5: Concurrent Operations Tests
await this.runConcurrentOperationTests();
// Test Suite 6: Error Handling and Recovery Tests
await this.runErrorHandlingTests();
// Calculate final results
this.testResults.executionTime = Date.now() - this.startTime;
this.generateTestReport();
return this.testResults;
} catch (error) {
this.testResults.errorSummary.criticalErrors.push(`Test execution failed: ${error}`);
throw error;
}
}
/**
* Core Workflow Tests - Complete evolution cycles
*/
private async runCoreWorkflowTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('Core Workflow Tests', () => {
test('Complete Evolution Cycle', async () => {
const scenario = await this.environment!.scenarios.createCompleteEvolutionScenario();
const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(scenario));
expect(result.success).toBe(true);
expect(result.evolutionResult).toBeDefined();
if (result.evolutionResult) {
expect(result.evolutionResult.generations).toBeGreaterThan(0);
expect(result.evolutionResult.bestPrompt).toBeDefined();
}
this.testResults.passedTests++;
});
test('Trajectory Recording and Analysis', async () => {
const trajectory = await this.environment!.scenarios.createSampleTrajectory();
const saveResult = await this.environment!.trajectoryStore.save(trajectory);
expect(saveResult.success).toBe(true);
expect(saveResult.id).toBeDefined();
const loadedTrajectory = await this.environment!.trajectoryStore.load(saveResult.id!);
expect(loadedTrajectory).toBeDefined();
expect(loadedTrajectory!.id).toBe(trajectory.id);
this.testResults.passedTests++;
});
test('Pareto Frontier Optimization', async () => {
const candidates = await this.environment!.scenarios.createOptimizationCandidates();
for (const candidate of candidates) {
await this.environment!.paretoFrontier.addCandidate(candidate);
}
const frontier = this.environment!.paretoFrontier.getFrontier();
expect(frontier.length).toBeGreaterThan(0);
expect(frontier.length).toBeLessThanOrEqual(candidates.length);
// Verify Pareto optimality
for (let i = 0; i < frontier.length; i++) {
for (let j = 0; j < frontier.length; j++) {
if (i !== j) {
const candidateI = frontier[i]?.candidate;
const candidateJ = frontier[j]?.candidate;
if (candidateI && candidateJ) {
expect(this.environment!.paretoFrontier.isDominated(
candidateI,
candidateJ
)).toBe(false);
}
}
}
}
this.testResults.passedTests++;
});
this.testResults.totalTests += 3;
});
}
/**
* MCP Tool Integration Tests
*/
private async runMCPToolTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('MCP Tool Integration Tests', () => {
test('gepa_start_evolution Tool', async () => {
const params: StartEvolutionParams = {
taskDescription: 'Test task for evolution',
seedPrompt: 'Test seed prompt',
config: {
populationSize: 5,
maxGenerations: 3,
mutationRate: 0.2,
},
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_start_evolution',
params as unknown as Record<string, unknown>
);
expect(result.success).toBe(true);
expect(result.content).toBeDefined();
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Evolution Process Started');
}
this.testResults.passedTests++;
});
test('gepa_record_trajectory Tool', async () => {
const params: RecordTrajectoryParams = {
promptId: 'test-prompt-1',
taskId: 'test-task-1',
executionSteps: [
{
stepNumber: 1,
action: 'initialize',
timestamp: new Date(),
},
{
stepNumber: 2,
action: 'execute',
timestamp: new Date(),
},
],
result: {
success: true,
score: 0.85,
output: { result: 'test output' },
},
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_record_trajectory',
params as unknown as Record<string, unknown>
);
expect(result.success).toBe(true);
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Trajectory Recorded Successfully');
}
this.testResults.passedTests++;
});
test('gepa_evaluate_prompt Tool', async () => {
const params: EvaluatePromptParams = {
promptId: 'test-prompt-1',
taskIds: ['task-1', 'task-2'],
rolloutCount: 3,
parallel: true,
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_evaluate_prompt',
params as unknown as Record<string, unknown>
);
expect(result.success).toBe(true);
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Prompt Evaluation Complete');
}
this.testResults.passedTests++;
});
test('gepa_reflect Tool', async () => {
// First create some test trajectories
await this.environment!.scenarios.createFailureTrajectories();
const params: ReflectParams = {
trajectoryIds: ['trajectory-1', 'trajectory-2'],
targetPromptId: 'test-prompt-1',
analysisDepth: 'deep',
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_reflect',
params as unknown as Record<string, unknown>
);
expect(result.success).toBe(true);
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Reflection Analysis Complete');
}
this.testResults.passedTests++;
});
test('gepa_get_pareto_frontier Tool', async () => {
// Populate frontier with test data
await this.environment!.scenarios.populateParetoFrontier();
const params: GetParetoFrontierParams = {
minPerformance: 0.5,
limit: 5,
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_get_pareto_frontier',
params as Record<string, unknown>
);
expect(result.success).toBe(true);
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Pareto Frontier Results');
}
this.testResults.passedTests++;
});
test('gepa_select_optimal Tool', async () => {
const params: SelectOptimalParams = {
taskContext: 'Test optimization context',
performanceWeight: 0.8,
diversityWeight: 0.2,
};
const result = await this.environment!.testHelpers.callMCPTool(
'gepa_select_optimal',
params as Record<string, unknown>
);
expect(result.success).toBe(true);
if (result.content && result.content[0]) {
expect(result.content[0].text).toContain('Optimal Candidate Selected');
}
this.testResults.passedTests++;
});
this.testResults.totalTests += 6;
});
}
/**
* Performance and Load Tests
*/
private async runPerformanceTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('Performance and Load Tests', () => {
test('Concurrent Evolution Cycles', async () => {
const concurrentEvolutions = 3;
const evolutionPromises = [];
for (let i = 0; i < concurrentEvolutions; i++) {
const promise = this.environment!.scenarios.createConcurrentEvolutionScenario(i);
evolutionPromises.push(promise);
}
const startTime = Date.now();
const results = await Promise.all(evolutionPromises);
const executionTime = Date.now() - startTime;
expect(results.length).toBe(concurrentEvolutions);
expect(results.every(r => r.success)).toBe(true);
expect(executionTime).toBeLessThan(this.config.performanceThresholds.evolutionTime * 2);
this.testResults.performanceMetrics.concurrentOperations = concurrentEvolutions;
this.testResults.passedTests++;
});
test('Large Population Handling', async () => {
const largePopulationSize = 100;
const scenario = await this.environment!.scenarios.createLargePopulationScenario(largePopulationSize);
const startTime = Date.now();
const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(scenario));
const executionTime = Date.now() - startTime;
expect(result.success).toBe(true);
expect(executionTime).toBeLessThan(this.config.performanceThresholds.evolutionTime * 3);
this.testResults.performanceMetrics.avgEvolutionTime = executionTime;
this.testResults.passedTests++;
});
test('Memory Usage Under Load', async () => {
const initialMemory = process.memoryUsage().heapUsed;
// Create high memory load scenario
await this.environment!.scenarios.createHighMemoryLoadScenario();
const peakMemory = process.memoryUsage().heapUsed;
const memoryIncrease = peakMemory - initialMemory;
// Force garbage collection if available
if (global.gc) {
global.gc();
}
const finalMemory = process.memoryUsage().heapUsed;
const memoryLeakSuspected = (finalMemory - initialMemory) > (memoryIncrease * 0.5);
expect(memoryIncrease).toBeLessThan(100 * 1024 * 1024); // Less than 100MB increase
expect(memoryLeakSuspected).toBe(false);
this.testResults.memoryUsage.peakUsage = peakMemory;
this.testResults.memoryUsage.leakDetected = memoryLeakSuspected;
this.testResults.passedTests++;
});
test('Response Time Benchmarks', async () => {
const benchmarks = await this.environment!.benchmarks.runComprehensiveBenchmarks();
expect(benchmarks.trajectoryRecording.averageTime).toBeLessThan(
this.config.performanceThresholds.trajectoryRecording
);
expect(benchmarks.paretoQuery.averageTime).toBeLessThan(
this.config.performanceThresholds.paretoFrontierQuery
);
expect(benchmarks.memoryOperations.averageTime).toBeLessThan(
this.config.performanceThresholds.memoryOperations
);
this.testResults.performanceMetrics.avgTrajectoryRecording = benchmarks.trajectoryRecording.averageTime;
this.testResults.performanceMetrics.avgParetoQuery = benchmarks.paretoQuery.averageTime;
this.testResults.performanceMetrics.avgMemoryOperation = benchmarks.memoryOperations.averageTime;
this.testResults.passedTests++;
});
this.testResults.totalTests += 4;
});
}
/**
* Memory System Tests
*/
private async runMemorySystemTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('Memory System Tests', () => {
test('Automated Memory Updates', async () => {
const trajectory = await this.environment!.scenarios.createSampleTrajectory();
const saveResult = await this.environment!.trajectoryStore.save(trajectory);
expect(saveResult.success).toBe(true);
// Verify memory auto-updates
const memoryStats = await this.environment!.testHelpers.getMemoryStats();
expect(memoryStats.totalTrajectories).toBeGreaterThan(0);
expect(memoryStats.lastUpdateTime).toBeDefined();
this.testResults.passedTests++;
});
test('Memory Optimization Triggers', async () => {
// Fill memory to trigger optimization
await this.environment!.scenarios.fillMemoryToCapacity();
const beforeOptimization = await this.environment!.testHelpers.getMemoryStats();
// Trigger optimization manually
await this.environment!.testHelpers.triggerMemoryOptimization();
const afterOptimization = await this.environment!.testHelpers.getMemoryStats();
expect(afterOptimization.usedSpace).toBeLessThan(beforeOptimization.usedSpace);
expect(afterOptimization.optimizationCount).toBeGreaterThan(beforeOptimization.optimizationCount);
this.testResults.passedTests++;
});
test('Cross-System Memory Sync', async () => {
const trajectory1 = await this.environment!.scenarios.createSampleTrajectory();
const trajectory2 = await this.environment!.scenarios.createSampleTrajectory();
// Save to different systems
await this.environment!.trajectoryStore.save(trajectory1);
await this.environment!.paretoFrontier.addCandidate(trajectory2.steps[0] as any);
// Verify cross-system sync
const syncResult = await this.environment!.testHelpers.performCrossSystemSync();
expect(syncResult.success).toBe(true);
expect(syncResult.synchronizedEntities).toBeGreaterThan(0);
this.testResults.passedTests++;
});
test('Recovery from Memory Errors', async () => {
// Simulate memory corruption
await this.environment!.scenarios.simulateMemoryCorruption();
const recoveryResult = await this.environment!.testHelpers.attemptMemoryRecovery();
expect(recoveryResult.success).toBe(true);
expect(recoveryResult.recoveredEntities).toBeGreaterThan(0);
// Verify system functionality after recovery
const testTrajectory = await this.environment!.scenarios.createSampleTrajectory();
const saveResult = await this.environment!.trajectoryStore.save(testTrajectory);
expect(saveResult.success).toBe(true);
this.testResults.passedTests++;
this.testResults.errorSummary.recoveredErrors.push('Memory corruption recovered successfully');
});
this.testResults.totalTests += 4;
});
}
/**
* Concurrent Operations Tests
*/
private async runConcurrentOperationTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('Concurrent Operations Tests', () => {
test('Concurrent Tool Execution', async () => {
const concurrentCalls = 5;
const toolPromises = [];
for (let i = 0; i < concurrentCalls; i++) {
const promise = this.environment!.testHelpers.callMCPTool('gepa_evaluate_prompt', {
promptId: `concurrent-prompt-${i}`,
taskIds: [`task-${i}`],
rolloutCount: 2,
});
toolPromises.push(promise);
}
const results = await Promise.all(toolPromises);
expect(results.length).toBe(concurrentCalls);
expect(results.every(r => r.success)).toBe(true);
this.testResults.passedTests++;
});
test('Parallel Memory Access', async () => {
const parallelOperations = 10;
const operationPromises = [];
for (let i = 0; i < parallelOperations; i++) {
const trajectory = await this.environment!.scenarios.createSampleTrajectory();
trajectory.id = `parallel-trajectory-${i}`;
const promise = this.environment!.trajectoryStore.save(trajectory);
operationPromises.push(promise);
}
const results = await Promise.all(operationPromises);
expect(results.length).toBe(parallelOperations);
expect(results.every(r => r.success)).toBe(true);
// Verify no data corruption
for (let i = 0; i < parallelOperations; i++) {
const loaded = await this.environment!.trajectoryStore.load(`parallel-trajectory-${i}`);
expect(loaded).toBeDefined();
expect(loaded!.id).toBe(`parallel-trajectory-${i}`);
}
this.testResults.passedTests++;
});
test('Concurrent Evolution and Analysis', async () => {
const evolutionPromise = this.environment!.scenarios.createCompleteEvolutionScenario();
const analysisPromise = this.environment!.scenarios.createReflectionAnalysisScenario();
const [evolutionResult, analysisResult] = await Promise.all([
this.environment!.testHelpers.executeScenario(evolutionPromise),
this.environment!.testHelpers.executeScenario(analysisPromise),
]);
expect(evolutionResult.success).toBe(true);
expect(analysisResult.success).toBe(true);
this.testResults.passedTests++;
});
this.testResults.totalTests += 3;
});
}
/**
* Error Handling and Recovery Tests
*/
private async runErrorHandlingTests(): Promise<void> {
if (!this.environment) throw new Error('Environment not initialized');
describe('Error Handling and Recovery Tests', () => {
test('Invalid MCP Tool Parameters', async () => {
try {
await this.environment!.testHelpers.callMCPTool('gepa_start_evolution', {
// Missing required taskDescription
seedPrompt: 'test',
} as any);
// Should not reach here
expect(false).toBe(true);
} catch (error) {
expect(error).toBeDefined();
this.testResults.passedTests++;
this.testResults.errorSummary.recoveredErrors.push('Invalid parameters handled correctly');
}
});
test('Component Failure Recovery', async () => {
// Simulate LLM adapter failure
await this.environment!.scenarios.simulateComponentFailure('llmAdapter');
const recoveryResult = await this.environment!.testHelpers.attemptComponentRecovery('llmAdapter');
expect(recoveryResult.success).toBe(true);
// Verify system still functions
const testResult = await this.environment!.testHelpers.callMCPTool('gepa_evaluate_prompt', {
promptId: 'recovery-test',
taskIds: ['recovery-task'],
});
expect(testResult.success).toBe(true);
this.testResults.passedTests++;
});
test('Resource Exhaustion Handling', async () => {
// Simulate resource exhaustion
const exhaustionScenario = await this.environment!.scenarios.createResourceExhaustionScenario();
const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(exhaustionScenario));
// Should handle gracefully without crashing
expect(result.completed).toBe(true);
expect(result.errorHandled).toBe(true);
this.testResults.passedTests++;
});
test('Data Corruption Detection and Recovery', async () => {
// Introduce data corruption
await this.environment!.scenarios.introduceDataCorruption();
const detectionResult = await this.environment!.testHelpers.runCorruptionDetection();
expect(detectionResult.corruptionDetected).toBe(true);
const recoveryResult = await this.environment!.testHelpers.attemptDataRecovery();
expect(recoveryResult.success).toBe(true);
this.testResults.passedTests++;
this.testResults.errorSummary.recoveredErrors.push('Data corruption detected and recovered');
});
this.testResults.totalTests += 4;
});
}
/**
* Generate comprehensive test report
*/
private generateTestReport(): void {
const successRate = (this.testResults.passedTests / this.testResults.totalTests) * 100;
// eslint-disable-next-line no-console
console.log('\nš E2E Test Results Summary');
// eslint-disable-next-line no-console
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
// eslint-disable-next-line no-console
console.log(`Total Tests: ${this.testResults.totalTests}`);
// eslint-disable-next-line no-console
console.log(`Passed: ${this.testResults.passedTests} (${successRate.toFixed(1)}%)`);
// eslint-disable-next-line no-console
console.log(`Failed: ${this.testResults.failedTests}`);
// eslint-disable-next-line no-console
console.log(`Skipped: ${this.testResults.skippedTests}`);
// eslint-disable-next-line no-console
console.log(`Execution Time: ${(this.testResults.executionTime / 1000).toFixed(2)}s`);
// eslint-disable-next-line no-console
console.log('\nā” Performance Metrics');
// eslint-disable-next-line no-console
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
// eslint-disable-next-line no-console
console.log(`Avg Evolution Time: ${this.testResults.performanceMetrics.avgEvolutionTime}ms`);
// eslint-disable-next-line no-console
console.log(`Avg Trajectory Recording: ${this.testResults.performanceMetrics.avgTrajectoryRecording}ms`);
// eslint-disable-next-line no-console
console.log(`Avg Pareto Query: ${this.testResults.performanceMetrics.avgParetoQuery}ms`);
// eslint-disable-next-line no-console
console.log(`Avg Memory Operation: ${this.testResults.performanceMetrics.avgMemoryOperation}ms`);
// eslint-disable-next-line no-console
console.log(`Concurrent Operations: ${this.testResults.performanceMetrics.concurrentOperations}`);
// eslint-disable-next-line no-console
console.log('\nš¾ Memory Usage');
// eslint-disable-next-line no-console
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
// eslint-disable-next-line no-console
console.log(`Peak Usage: ${(this.testResults.memoryUsage.peakUsage / 1024 / 1024).toFixed(2)}MB`);
// eslint-disable-next-line no-console
console.log(`Leak Detected: ${this.testResults.memoryUsage.leakDetected ? 'ā' : 'ā
'}`);
if (this.testResults.errorSummary.criticalErrors.length > 0) {
// eslint-disable-next-line no-console
console.log('\nšØ Critical Errors');
// eslint-disable-next-line no-console
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
this.testResults.errorSummary.criticalErrors.forEach(error => // eslint-disable-next-line no-console
console.log(`ā ${error}`));
}
if (this.testResults.errorSummary.recoveredErrors.length > 0) {
// eslint-disable-next-line no-console
console.log('\nš Recovered Errors');
// eslint-disable-next-line no-console
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
this.testResults.errorSummary.recoveredErrors.forEach(error => // eslint-disable-next-line no-console
console.log(`ā
${error}`));
}
}
/**
* Cleanup test environment
*/
async cleanup(): Promise<void> {
if (!this.environment) return;
try {
await Promise.all([
this.environment.llmAdapter.shutdown(),
this.environment.promptMutator.shutdown(),
]);
// Clean up temporary files
await this.removeDirectory(this.environment.tempDir);
// eslint-disable-next-line no-console
console.log('ā
E2E test environment cleaned up successfully');
} catch (error) {
// eslint-disable-next-line no-console
console.error('ā Error during E2E test cleanup:', error);
}
}
/**
* Utility: Create directory
*/
private async createDirectory(path: string): Promise<void> {
const { mkdir } = await import('fs/promises');
await mkdir(path, { recursive: true });
}
/**
* Utility: Remove directory
*/
private async removeDirectory(path: string): Promise<void> {
const { rm } = await import('fs/promises');
await rm(path, { recursive: true, force: true });
}
}