runTestSuite method
Implementation
Future<void> runTestSuite() async {
try {
// print('Running LuaLike test suite in $mode mode...');
print("Files in test suite: $testSuitePath");
final testDir = Directory(testSuitePath);
if (!testDir.existsSync()) {
print('Error: Test suite directory not found: $testSuitePath');
exit(1);
}
// Create logs directory
final logDir = Directory(logDirPath);
if (!logDir.existsSync()) {
logDir.createSync(recursive: true);
}
print("Finding test files in $testSuitePath");
final allTestFiles = await _getTestFiles(testDir);
// Filter test files based on categories and pattern
final testFiles = _filterTestFiles(allTestFiles);
if (testFiles.isEmpty) {
print('No test files found matching the specified criteria.');
exit(0);
}
print('Found ${testFiles.length} test files to run.');
progressBar = ProgressBar(total: testFiles.length);
final suiteStartTime = DateTime.now();
int passedCount = 0;
int failedCount = 0;
int skippedCount = 0;
if (parallel) {
print('Running tests in parallel with $parallelJobs jobs...');
final chunks = _chunkList(testFiles, parallelJobs);
final futures = chunks.map((chunk) => _runTestChunk(chunk, testDir));
final results = await Future.wait(futures);
for (final result in results) {
passedCount += result['passed'] as int;
failedCount += result['failed'] as int;
skippedCount += result['skipped'] as int;
}
} else {
for (final testFile in testFiles) {
final relativePath = testFile.path.replaceFirst(
testDir.path + Platform.pathSeparator,
'',
);
// Check if test should be skipped
if (skipList.contains(relativePath)) {
if (verbose) {
print('\n--- Skipping test: $relativePath (in skip list) ---');
}
skippedCount++;
await progressBar.increment();
results[relativePath] = TestResult(
name: relativePath,
passed: true,
skipped: true,
duration: Duration.zero,
category: _getCategoryForTest(relativePath),
);
continue;
}
if (verbose) {
print('\n--- Running test: $relativePath ---');
Logger.setEnabled(true);
}
final testStartTime = DateTime.now();
final logBuffer = StringBuffer();
logBuffer.writeln('=== Test: $relativePath ===');
logBuffer.writeln('Start time: $testStartTime');
// logBuffer.writeln('Mode: $mode');
logBuffer.writeln(
'Category: ${_getCategoryForTest(relativePath) ?? "uncategorized"}',
);
try {
final sourceCode = await testFile.readAsString();
logBuffer.writeln('\n--- Source Code ---');
logBuffer.writeln(sourceCode);
logBuffer.writeln('\n--- Execution ---');
final _ = await executeCode(
sourceCode,
// mode,
onInterpreterSetup: (interpreter) {
if (useInternalTests) {
_injectInternalTestFunctions(interpreter.globals);
}
},
);
final testEndTime = DateTime.now();
final testDuration = testEndTime.difference(testStartTime);
logBuffer.writeln('\n--- Result ---');
logBuffer.writeln('Status: PASSED');
logBuffer.writeln('Duration: ${testDuration.inMilliseconds} ms');
if (verbose) {
print(
'Test passed: $relativePath (${testDuration.inMilliseconds} ms)',
);
}
passedCount++;
results[relativePath] = TestResult(
name: relativePath,
passed: true,
duration: testDuration,
category: _getCategoryForTest(relativePath),
);
} catch (e, stackTrace) {
final testEndTime = DateTime.now();
final testDuration = testEndTime.difference(testStartTime);
logBuffer.writeln('\n--- Result ---');
logBuffer.writeln('Status: FAILED');
logBuffer.writeln('Error: $e');
logBuffer.writeln('Stack trace:');
logBuffer.writeln(stackTrace);
logBuffer.writeln('Duration: ${testDuration.inMilliseconds} ms');
if (verbose) {
print('Test failed: $relativePath');
print('Error: $e');
}
failedCount++;
results[relativePath] = TestResult(
name: relativePath,
passed: false,
errorMessage: e.toString(),
duration: testDuration,
category: _getCategoryForTest(relativePath),
);
}
// Write test log
final sanitizedName = relativePath.replaceAll(RegExp(r'[\/\\]'), '_');
final logFile = File('$logDirPath/$sanitizedName.log');
logFile.writeAsStringSync(logBuffer.toString());
progressBar.increment();
}
}
final suiteEndTime = DateTime.now();
final suiteDuration = suiteEndTime.difference(suiteStartTime);
// Create summary report
final reportBuffer = StringBuffer();
reportBuffer.writeln('=== LuaLike Test Suite Summary ===');
reportBuffer.writeln('Date: $suiteStartTime');
// reportBuffer.writeln('Mode: $mode');
reportBuffer.writeln('Total tests: ${testFiles.length}');
reportBuffer.writeln('Passed: $passedCount');
reportBuffer.writeln('Failed: $failedCount');
reportBuffer.writeln('Skipped: $skippedCount');
reportBuffer.writeln('Duration: ${suiteDuration.inSeconds} seconds');
// Add category statistics
reportBuffer.writeln('\n=== Category Statistics ===');
final categoryStats = _getCategoryStatistics();
for (final entry in categoryStats.entries) {
final category = entry.key;
final stats = entry.value;
reportBuffer.writeln(
'$category: ${stats['total']} tests, ${stats['passed']} passed, ${stats['failed']} failed, ${stats['skipped']} skipped',
);
}
reportBuffer.writeln('\n=== Detailed Results ===');
for (final entry
in results.entries.toList()..sort((a, b) => a.key.compareTo(b.key))) {
final result = entry.value;
if (result.skipped) {
reportBuffer.writeln('${result.name}: SKIPPED');
} else {
reportBuffer.writeln(
'${result.name}: ${result.passed ? "PASSED" : "FAILED"} (${result.duration.inMilliseconds} ms)',
);
if (!result.passed) {
reportBuffer.writeln(' Error: ${result.errorMessage}');
}
}
}
// Write summary report
final reportFile = File('$logDirPath/summary_report.txt');
reportFile.writeAsStringSync(reportBuffer.toString());
// Write JSON report for programmatic consumption
final jsonReport = {
'timestamp': suiteStartTime.toIso8601String(),
// 'mode': mode.toString(),
'totalTests': testFiles.length,
'passed': passedCount,
'failed': failedCount,
'skipped': skippedCount,
'durationMs': suiteDuration.inMilliseconds,
'categoryStats': categoryStats,
'results': results.values.map((r) => r.toJson()).toList(),
};
final jsonReportFile = File('$logDirPath/report.json');
jsonReportFile.writeAsStringSync(jsonEncode(jsonReport));
print('\n--- Test Results ---');
print('Total tests: ${testFiles.length}');
print('Passed: $passedCount');
print('Failed: $failedCount');
print('Skipped: $skippedCount');
print('Duration: ${suiteDuration.inSeconds} seconds');
// Print category statistics
print('\n--- Category Statistics ---');
for (final entry in categoryStats.entries) {
final category = entry.key;
final stats = entry.value;
print(
'$category: ${stats['total']} tests, ${stats['passed']} passed, ${stats['failed']} failed, ${stats['skipped']} skipped',
);
}
print('\nLog files written to: $logDirPath');
print('Summary report: ${reportFile.path}');
if (failedCount > 0) {
exit(1); // Indicate test failure
}
} catch (e, stackTrace) {
print('\nError running test suite: $e');
print(stackTrace);
exit(2);
}
}