@@ -277,14 +277,14 @@ Future<int> _flutterTest({
277277 final suites = < int , TestSuite > {};
278278 final groups = < int , TestGroup > {};
279279 final tests = < int , Test > {};
280- final failedTests = < int > [] ;
280+ final failedTestErrorMessages = < int , String > {} ;
281281
282282 var successCount = 0 ;
283283 var skipCount = 0 ;
284284
285285 String computeStats () {
286286 final passingTests = successCount.formatSuccess ();
287- final failingTests = failedTests .length.formatFailure ();
287+ final failingTests = failedTestErrorMessages .length.formatFailure ();
288288 final skippedTests = skipCount.formatSkipped ();
289289 final result = [passingTests, failingTests, skippedTests]
290290 ..removeWhere ((element) => element.isEmpty);
@@ -327,9 +327,17 @@ Future<int> _flutterTest({
327327
328328 if (event is ErrorTestEvent ) {
329329 stderr ('$clearLine ${event .error }' );
330+
330331 if (event.stackTrace.trim ().isNotEmpty) {
331332 stderr ('$clearLine ${event .stackTrace }' );
332333 }
334+
335+ final pathFromStackTrace = getPathFromStackTrace (event.stackTrace);
336+
337+ final testErrorDescription =
338+ pathFromStackTrace ?? event.error.replaceAll ('\n ' , ' ' );
339+
340+ failedTestErrorMessages[event.testID] = testErrorDescription;
333341 }
334342
335343 if (event is TestDoneEvent ) {
@@ -347,7 +355,6 @@ Future<int> _flutterTest({
347355 successCount++ ;
348356 } else {
349357 stderr ('$clearLine ${test .name } ${suite .path } (FAILED)' );
350- failedTests.add (test.id);
351358 }
352359
353360 final timeElapsed = Duration (milliseconds: event.time).formatted ();
@@ -369,24 +376,19 @@ Future<int> _flutterTest({
369376
370377 if (event.success != true ) {
371378 assert (
372- failedTests .isNotEmpty,
373- 'Invalid state: test event report as faield but no failed tests '
379+ failedTestErrorMessages .isNotEmpty,
380+ 'Invalid state: test event report as failed but no failed tests '
374381 'were gathered' ,
375382 );
376383 final title = styleBold.wrap ('Failing Tests:' );
377- final lines = failedTests.fold <StringBuffer >(
378- StringBuffer ('$clearLine $title \n ' ),
379- (previousValue, testId) {
380- final test = tests[testId];
381- if (test != null ) {
382- final suitePath = suites[test.suiteID]? .path ?? '' ;
383- previousValue.writeln (
384- '$clearLine - $suitePath :${test .line }:${test .column }' ,
385- );
386- }
387- return previousValue;
388- },
389- );
384+
385+ final lines = StringBuffer ('$clearLine $title \n ' );
386+ for (final errorMessage in failedTestErrorMessages.values) {
387+ lines.writeln (
388+ '$clearLine - $errorMessage ' ,
389+ );
390+ }
391+
390392 stderr (lines.toString ());
391393 }
392394 }
@@ -459,3 +461,40 @@ extension on String {
459461 return '...$truncated ' ;
460462 }
461463}
464+
465+ String ? getPathFromStackTrace (String stackTrace) {
466+ final trimmedStackTrace = stackTrace.trim ();
467+
468+ if (trimmedStackTrace.isEmpty) {
469+ return null ;
470+ }
471+
472+ final splittedStackTrace =
473+ trimmedStackTrace.split ('\n ' ).where ((element) => element.isNotEmpty);
474+
475+ if (splittedStackTrace.isEmpty) {
476+ return null ;
477+ }
478+
479+ final lastLine = splittedStackTrace.last.trim ();
480+
481+ if (lastLine.isEmpty) {
482+ return null ;
483+ }
484+
485+ final lastLineIterator = lastLine.split (' ' ).iterator;
486+
487+ if (! lastLineIterator.moveNext ()) {
488+ return null ;
489+ }
490+
491+ final path = p.normalize (lastLineIterator.current);
492+ if (! File (path).existsSync ()) {
493+ return null ;
494+ }
495+ if (! lastLineIterator.moveNext ()) {
496+ return path;
497+ }
498+
499+ return '$path :${lastLineIterator .current }' ;
500+ }
0 commit comments