55using System . CommandLine . Help ;
66using System . Globalization ;
77using System . Text . RegularExpressions ;
8+ using Microsoft . CodeAnalysis ;
89using Microsoft . DotNet . Cli . Commands . Test ;
910using Microsoft . DotNet . Cli . Commands . Test . Terminal ;
1011using FlatException = Microsoft . DotNet . Cli . Commands . Test . Terminal . FlatException ;
@@ -51,6 +52,7 @@ internal event EventHandler OnProgressStopUpdate
5152 private readonly uint ? _originalConsoleMode ;
5253 private bool _isDiscovery ;
5354 private bool _isHelp ;
55+ private bool _isRetry ;
5456 private DateTimeOffset ? _testExecutionStartTime ;
5557
5658 private DateTimeOffset ? _testExecutionEndTime ;
@@ -152,28 +154,52 @@ public TerminalTestReporter(IConsole console, TerminalTestReporterOptions option
152154 _terminalWithProgress = terminalWithProgress ;
153155 }
154156
155- public void TestExecutionStarted ( DateTimeOffset testStartTime , int workerCount , bool isDiscovery , bool isHelp )
157+ public void TestExecutionStarted ( DateTimeOffset testStartTime , int workerCount , bool isDiscovery , bool isHelp , bool isRetry )
156158 {
157159 _isDiscovery = isDiscovery ;
158160 _isHelp = isHelp ;
161+ _isRetry = isRetry ;
159162 _testExecutionStartTime = testStartTime ;
160163 _terminalWithProgress . StartShowingProgress ( workerCount ) ;
161164 }
162165
163- public void AssemblyRunStarted ( string assembly , string ? targetFramework , string ? architecture , string ? executionId )
166+ public void AssemblyRunStarted ( string assembly , string ? targetFramework , string ? architecture , string ? executionId , string ? instanceId )
164167 {
168+ var assemblyRun = GetOrAddAssemblyRun ( assembly , targetFramework , architecture , executionId ) ;
169+ assemblyRun . Tries . Add ( instanceId ) ;
170+
171+ if ( _isRetry )
172+ {
173+ // When we are retrying the new assembly run should ignore all previously failed tests and
174+ // clear all errors. We restarted the run and will retry all failed tests.
175+ //
176+ // In case of folded dynamic data tests we do not know how many tests we will get in each run,
177+ // if more or less, or the same amount as before,and we also will rerun tests that passed previously
178+ // because we are unable to run just a single test from that dynamic data source.
179+ // This will cause the total number of tests to differ between runs, and there is nothing we can do about it.
180+ assemblyRun . TotalTests -= assemblyRun . FailedTests ;
181+ assemblyRun . RetriedFailedTests += assemblyRun . FailedTests ;
182+ assemblyRun . FailedTests = 0 ;
183+ assemblyRun . ClearAllMessages ( ) ;
184+ }
185+
165186 if ( _options . ShowAssembly && _options . ShowAssemblyStartAndComplete )
166187 {
167188 _terminalWithProgress . WriteToTerminal ( terminal =>
168189 {
190+ if ( _isRetry )
191+ {
192+ terminal . SetColor ( TerminalColor . DarkGray ) ;
193+ terminal . Append ( $ "({ string . Format ( LocalizableStrings . Try , assemblyRun . Tries . Count ) } ) ") ;
194+ terminal . ResetColor ( ) ;
195+ }
196+
169197 terminal . Append ( _isDiscovery ? LocalizableStrings . DiscoveringTestsFrom : LocalizableStrings . RunningTestsFrom ) ;
170198 terminal . Append ( ' ' ) ;
171199 AppendAssemblyLinkTargetFrameworkAndArchitecture ( terminal , assembly , targetFramework , architecture ) ;
172200 terminal . AppendLine ( ) ;
173201 } ) ;
174202 }
175-
176- GetOrAddAssemblyRun ( assembly , targetFramework , architecture , executionId ) ;
177203 }
178204
179205 private TestProgressState GetOrAddAssemblyRun ( string assembly , string ? targetFramework , string ? architecture , string ? executionId )
@@ -306,6 +332,7 @@ private void AppendTestRunSummary(ITerminal terminal)
306332 int failed = _assemblies . Values . Sum ( t => t . FailedTests ) ;
307333 int passed = _assemblies . Values . Sum ( t => t . PassedTests ) ;
308334 int skipped = _assemblies . Values . Sum ( t => t . SkippedTests ) ;
335+ int retried = _assemblies . Values . Sum ( t => t . RetriedFailedTests ) ;
309336 int error = _assemblies . Values . Sum ( t => ! t . Success && ( t . TotalTests == 0 || t . FailedTests == 0 ) ? 1 : 0 ) ;
310337 TimeSpan runDuration = _testExecutionStartTime != null && _testExecutionEndTime != null ? ( _testExecutionEndTime - _testExecutionStartTime ) . Value : TimeSpan . Zero ;
311338
@@ -316,6 +343,7 @@ private void AppendTestRunSummary(ITerminal terminal)
316343
317344 string errorText = $ "{ SingleIndentation } error: { error } ";
318345 string totalText = $ "{ SingleIndentation } total: { total } ";
346+ string retriedText = $ " (+{ retried } retried)";
319347 string failedText = $ "{ SingleIndentation } failed: { failed } ";
320348 string passedText = $ "{ SingleIndentation } succeeded: { passed } ";
321349 string skippedText = $ "{ SingleIndentation } skipped: { skipped } ";
@@ -330,7 +358,15 @@ private void AppendTestRunSummary(ITerminal terminal)
330358 }
331359
332360 terminal . ResetColor ( ) ;
333- terminal . AppendLine ( totalText ) ;
361+ terminal . Append ( totalText ) ;
362+ if ( retried > 0 )
363+ {
364+ terminal . SetColor ( TerminalColor . DarkGray ) ;
365+ terminal . Append ( retriedText ) ;
366+ terminal . ResetColor ( ) ;
367+ }
368+ terminal . AppendLine ( ) ;
369+
334370 if ( colorizeFailed )
335371 {
336372 terminal . SetColor ( TerminalColor . Red ) ;
@@ -405,44 +441,12 @@ private static void AppendAssemblyResult(ITerminal terminal, bool succeeded, int
405441 }
406442 }
407443
408- internal void TestCompleted (
409- string assembly ,
410- string ? targetFramework ,
411- string ? architecture ,
412- string ? executionId ,
413- string testNodeUid ,
414- string displayName ,
415- TestOutcome outcome ,
416- TimeSpan duration ,
417- string ? errorMessage ,
418- Exception ? exception ,
419- string ? expected ,
420- string ? actual ,
421- string ? standardOutput ,
422- string ? errorOutput )
423- {
424- FlatException [ ] flatExceptions = ExceptionFlattener . Flatten ( errorMessage , exception ) ;
425- TestCompleted (
426- assembly ,
427- targetFramework ,
428- architecture ,
429- executionId ,
430- testNodeUid ,
431- displayName ,
432- outcome ,
433- duration ,
434- flatExceptions ,
435- expected ,
436- actual ,
437- standardOutput ,
438- errorOutput ) ;
439- }
440-
441444 internal void TestCompleted (
442445 string assembly ,
443446 string ? targetFramework ,
444447 string ? architecture ,
445448 string ? executionId ,
449+ string instanceId ,
446450 string testNodeUid ,
447451 string displayName ,
448452 TestOutcome outcome ,
@@ -454,6 +458,7 @@ internal void TestCompleted(
454458 string ? errorOutput )
455459 {
456460 TestProgressState asm = _assemblies [ $ "{ assembly } |{ targetFramework } |{ architecture } |{ executionId } "] ;
461+ var attempt = asm . Tries . Count ;
457462
458463 if ( _options . ShowActiveTests )
459464 {
@@ -479,12 +484,21 @@ internal void TestCompleted(
479484 break ;
480485 }
481486
487+ if ( _isRetry && asm . Tries . Count > 1 && outcome == TestOutcome . Passed )
488+ {
489+ // This is a retry of a test, and the test succeeded, so these tests are potentially flaky.
490+ // Tests that come from dynamic data sources and previously succeeded will also run on the second attempt,
491+ // and most likely will succeed as well, so we will get them here, even though they are probably not flaky.
492+ asm . FlakyTests . Add ( testNodeUid ) ;
493+
494+ }
482495 _terminalWithProgress . UpdateWorker ( asm . SlotIndex ) ;
483496 if ( outcome != TestOutcome . Passed || GetShowPassedTests ( ) )
484497 {
485498 _terminalWithProgress . WriteToTerminal ( terminal => RenderTestCompleted (
486499 terminal ,
487500 assembly ,
501+ attempt ,
488502 targetFramework ,
489503 architecture ,
490504 displayName ,
@@ -507,6 +521,7 @@ private bool GetShowPassedTests()
507521 internal /* for testing */ void RenderTestCompleted (
508522 ITerminal terminal ,
509523 string assembly ,
524+ int attempt ,
510525 string ? targetFramework ,
511526 string ? architecture ,
512527 string displayName ,
@@ -541,6 +556,11 @@ private bool GetShowPassedTests()
541556
542557 terminal . SetColor ( color ) ;
543558 terminal . Append ( outcomeText ) ;
559+ if ( _isRetry )
560+ {
561+ terminal . SetColor ( TerminalColor . DarkGray ) ;
562+ terminal . Append ( $ " ({ string . Format ( LocalizableStrings . Try , attempt ) } )") ;
563+ }
544564 terminal . ResetColor ( ) ;
545565 terminal . Append ( ' ' ) ;
546566 terminal . Append ( displayName ) ;
@@ -1033,6 +1053,7 @@ public void TestInProgress(
10331053 string ? targetFramework ,
10341054 string ? architecture ,
10351055 string testNodeUid ,
1056+ string instanceId ,
10361057 string displayName ,
10371058 string ? executionId )
10381059 {
0 commit comments