133 lines
4.1 KiB
Dart
133 lines
4.1 KiB
Dart
#!/usr/bin/env dart
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:logger/web.dart';
|
|
|
|
/// Converts Flutter JSON test results to JUnit XML format
|
|
/// Usage: dart test_runner.dart [test_results.json] [output.xml]
|
|
void main(List<String> arguments) {
|
|
var logger = Logger(
|
|
printer: PrettyPrinter(methodCount: 2, errorMethodCount: 8, colors: true, printEmojis: true, dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart),
|
|
);
|
|
if (arguments.length < 2) {
|
|
logger.i('Usage: dart test_runner.dart <json_file> <xml_output>');
|
|
exit(1);
|
|
}
|
|
|
|
final jsonFile = arguments[0];
|
|
final xmlFile = arguments[1];
|
|
|
|
try {
|
|
final jsonContent = File(jsonFile).readAsStringSync();
|
|
final lines = jsonContent.trim().split('\n');
|
|
|
|
final tests = <TestResult>[];
|
|
int totalTests = 0;
|
|
int failures = 0;
|
|
int skipped = 0;
|
|
double duration = 0.0;
|
|
|
|
// Parse JSON lines from flutter test output
|
|
for (final line in lines) {
|
|
if (line.trim().isEmpty) continue;
|
|
|
|
try {
|
|
final data = jsonDecode(line) as Map<String, dynamic>;
|
|
final type = data['type'] as String?;
|
|
|
|
if (type == 'testStart') {
|
|
final test = data['test'] as Map<String, dynamic>;
|
|
final name = test['name'] as String;
|
|
final id = test['id'] as int;
|
|
tests.add(TestResult(id: id, name: name));
|
|
totalTests++;
|
|
} else if (type == 'testDone') {
|
|
final testId = data['testID'] as int;
|
|
final result = data['result'] as String;
|
|
final time = data['time'] as int? ?? 0;
|
|
final error = data['error'] as String?;
|
|
final stackTrace = data['stackTrace'] as String?;
|
|
|
|
duration += time / 1000.0; // Convert to seconds
|
|
|
|
final testIndex = tests.indexWhere((t) => t.id == testId);
|
|
if (testIndex != -1) {
|
|
tests[testIndex].result = result;
|
|
tests[testIndex].duration = time / 1000.0;
|
|
tests[testIndex].error = error;
|
|
tests[testIndex].stackTrace = stackTrace;
|
|
|
|
if (result == 'error' || result == 'failure') {
|
|
failures++;
|
|
} else if (result == 'skip') {
|
|
skipped++;
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Skip malformed JSON lines
|
|
logger.i('Warning: Could not parse line: $line');
|
|
}
|
|
}
|
|
|
|
// Generate JUnit XML
|
|
final xml = generateJUnitXML(tests, totalTests, failures, skipped, duration);
|
|
File(xmlFile).writeAsStringSync(xml);
|
|
|
|
logger.i('Converted ${tests.length} test results to JUnit XML: $xmlFile');
|
|
|
|
// Exit with error code if there were failures
|
|
if (failures > 0) {
|
|
exit(1);
|
|
}
|
|
} catch (e) {
|
|
logger.e('Error: $e');
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
class TestResult {
|
|
final int id;
|
|
final String name;
|
|
String result = 'pending';
|
|
double duration = 0.0;
|
|
String? error;
|
|
String? stackTrace;
|
|
|
|
TestResult({required this.id, required this.name});
|
|
}
|
|
|
|
String generateJUnitXML(List<TestResult> tests, int total, int failures, int skipped, double duration) {
|
|
final buffer = StringBuffer();
|
|
|
|
buffer.writeln('<?xml version="1.0" encoding="UTF-8"?>');
|
|
buffer.writeln('<testsuite name="Flutter Tests" tests="$total" failures="$failures" skipped="$skipped" time="$duration">');
|
|
|
|
for (final test in tests) {
|
|
final escapedName = _escapeXml(test.name);
|
|
buffer.writeln(' <testcase name="$escapedName" time="${test.duration}">');
|
|
|
|
if (test.result == 'error' || test.result == 'failure') {
|
|
final escapedError = _escapeXml(test.error ?? 'Test failed');
|
|
final escapedStackTrace = _escapeXml(test.stackTrace ?? '');
|
|
|
|
buffer.writeln(' <failure message="$escapedError">');
|
|
buffer.writeln(' <![CDATA[$escapedStackTrace]]>');
|
|
buffer.writeln(' </failure>');
|
|
} else if (test.result == 'skip') {
|
|
buffer.writeln(' <skipped/>');
|
|
}
|
|
|
|
buffer.writeln(' </testcase>');
|
|
}
|
|
|
|
buffer.writeln('</testsuite>');
|
|
return buffer.toString();
|
|
}
|
|
|
|
String _escapeXml(String text) {
|
|
return text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", ''');
|
|
}
|