internal void WriteRoundBox(ColorTextBuilder builder, string str, int leftPadding = 0, Color?color = null) { builder.AppendLine($"{UTF8Constants.RoundBoxTopLeft}{DisplayUtil.Pad(str.Length + 4, UTF8Constants.RoundBoxHorizontal)}{UTF8Constants.RoundBoxTopRight}{DisplayUtil.Pad(leftPadding)}", color ?? _colorScheme.Highlight); builder.AppendLine($"{UTF8Constants.RoundBoxVertical} {str} {UTF8Constants.RoundBoxVertical}{DisplayUtil.Pad(leftPadding)}", color ?? _colorScheme.Highlight); builder.AppendLine($"{UTF8Constants.RoundBoxBottomLeft}{DisplayUtil.Pad(str.Length + 4, UTF8Constants.RoundBoxHorizontal)}{UTF8Constants.RoundBoxBottomRight}{DisplayUtil.Pad(leftPadding)}", color ?? _colorScheme.Highlight); }
public override ColorTextBuilder Write(object parameters = null) { var allReports = (IEnumerable <DataEvent>)parameters; var builder = new ColorTextBuilder(); var lineSeparator = new string(UTF8Constants.HorizontalLine, !_console.IsOutputRedirected ? (Console.WindowWidth - 1) : DefaultBorderWidth); var showErrors = _configuration.GenerateReportType.HasFlag(GenerateReportType.Errors); var showStackTraces = _configuration.GenerateReportType.HasFlag(GenerateReportType.StackTraces); var showTestOutput = _configuration.GenerateReportType.HasFlag(GenerateReportType.TestOutput); if (showErrors || showStackTraces || showTestOutput) { var isPassed = allReports .SelectMany(x => x.Report.TestReports) .Count(x => x.TestStatus == TestStatus.Fail) == 0; if (!isPassed) { WriteRoundBox(builder, "FAILED TESTS", 0, _colorScheme.Error); } var testIndex = 0; var groupedByRun = allReports .GroupBy(x => x.RunNumber); var failedTestCases = groupedByRun .ToDictionary(x => x.Key, value => value.SelectMany(y => y.Report.TestReports.Where(z => z.TestStatus == TestStatus.Fail))); var lineSeparatorColor = _colorScheme.RaisedBackground; foreach (var testGroup in failedTestCases) { var runNumber = testGroup.Key; foreach (var test in testGroup.Value) { testIndex++; // write the failed test header if (!_console.IsOutputRedirected) { builder.AppendLine($"{DisplayUtil.Pad(Console.WindowWidth - 1)}", _colorScheme.Error, _colorScheme.DarkError); } var testIndexStr = $"#{testIndex}) "; if (failedTestCases.Count() > 1) { testIndexStr = $"#{runNumber}-{testIndex}) "; } builder.Append(testIndexStr, _colorScheme.DarkError); // write the test name only builder.Append(test.TestName, _colorScheme.Error); if (!_console.IsOutputRedirected) { builder.AppendLine($"{DisplayUtil.Pad(Console.WindowWidth - testIndexStr.Length - test.TestName.Length - 1)}", _colorScheme.Error); } else { builder.AppendLine(); } // write the test path + name (for Stack Trace Explorer) var fullName = $"{DisplayUtil.Pad(testIndexStr.Length)}{test.FullName}"; builder.Append(fullName, _colorScheme.DarkDuration); if (!_console.IsOutputRedirected) { builder.AppendLine($"{DisplayUtil.Pad(Console.WindowWidth - fullName.Length - 1)}", _colorScheme.Error); } else { builder.AppendLine(); } var runtimeVersion = $"{DisplayUtil.Pad(testIndexStr.Length)}{test.RuntimeVersion}"; builder.Append($"{runtimeVersion}", _colorScheme.DarkDefault); if (!_console.IsOutputRedirected) { builder.AppendLine($"{DisplayUtil.Pad(Console.WindowWidth - runtimeVersion.Length)}", _colorScheme.Error); } else { builder.AppendLine(); } builder.Append($" Duration ", _colorScheme.DarkDefault); builder.AppendLine($"{test.Duration.ToElapsedTime()}", _colorScheme.Duration); if (showErrors && !string.IsNullOrEmpty(test.ErrorMessage)) { builder.AppendLine($" Error Output ", _colorScheme.Bright); builder.AppendLine(lineSeparator, lineSeparatorColor); if (!_configuration.DontPrettify) { var errorMessage = ErrorEncoding.Format(test.ErrorMessage, _colorScheme); builder.Append(errorMessage); } else { builder.Append(test.ErrorMessage); } builder.AppendLine(); builder.AppendLine(lineSeparator, lineSeparatorColor); } if (showStackTraces && !string.IsNullOrEmpty(test.StackTrace)) { builder.AppendLine($" Stack Trace:", _colorScheme.Bright); builder.AppendLine(lineSeparator, lineSeparatorColor); if (!_configuration.DontPrettify) { builder.Append(StackTracePrettify.Format(test.StackTrace, _colorScheme)); } else { builder.Append(test.StackTrace); } builder.AppendLine(); builder.AppendLine(lineSeparator, lineSeparatorColor); } if (showTestOutput && !string.IsNullOrEmpty(test.TestOutput)) { builder.AppendLine($" Test Output: ", _colorScheme.Bright); builder.AppendLine(lineSeparator, lineSeparatorColor); if (!_configuration.DontPrettify) { builder.Append(ErrorEncoding.Format(test.TestOutput, _colorScheme)); } else { builder.Append(test.TestOutput); } builder.AppendLine(); builder.AppendLine(lineSeparator, lineSeparatorColor); } builder.AppendLine(Environment.NewLine); } } } return(builder); }
public void Draw(ViewContext context, long ticks) { if (_startTicks == 0) { _startTicks = ticks; context.Console.Clear(); } if (!context.Console.IsOutputRedirected) { // if the user has scrolled the page don't perform any drawing if (Console.WindowTop > 0) { return; } Console.CursorVisible = false; _performFullDraw = (_startTicks - ticks) % DefaultTickWait == 0; var windowWidth = Console.WindowWidth; var windowHeight = Console.WindowHeight; if (windowHeight != _previousWindowHeight) { _performFullDraw = true; } _previousWindowHeight = windowHeight; if (_performFullDraw) { ClearScreen(context); } var lineSeparator = DisplayUtil.Pad(Console.WindowWidth - 1, UTF8Constants.HorizontalLine); var yPos = 0; // figure out how many tests we can fit on screen var maxActiveTestsToDisplay = Console.WindowHeight - yPos - 2; var totalActiveTests = context.ActiveTests.Count(x => !x.IsQueuedForRemoval); var totalActiveTestFixtures = context.ActiveTestFixtures.Count(x => !x.IsQueuedForRemoval); var totalActiveAssemblies = context.ActiveAssemblies.Count(x => !x.IsQueuedForRemoval); if (totalActiveTests > 0 && totalActiveTestFixtures == 0) { // fix for older versions of nUnit that don't send the start test fixture event // it will still be incorrect, as it will treat parents of tests with multiple cases as a testfixture var parentIds = context.ActiveTests .Where(x => !x.IsQueuedForRemoval && !string.IsNullOrEmpty(x.Event.ParentId)) .Select(x => x.Event.ParentId) .Distinct(); totalActiveTestFixtures = context.ActiveTestSuites.Count(x => !x.IsQueuedForRemoval && parentIds.Contains(x.Event.Id)); } var totalPasses = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Pass); var totalFails = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail); var totalIgnored = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Skipped); var totalTestsProcessed = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest); WriteHeader(context); // write the summary of all test state context.Console.WriteAt(ColorTextBuilder.Create .Append("Tests state: ", context.ColorScheme.Bright) .Append($"Tests=", context.ColorScheme.Default) .Append($"{totalActiveTests} ", context.ColorScheme.Highlight) .Append($"Fixtures=", context.ColorScheme.Default) .Append($"{totalActiveTestFixtures} ", context.ColorScheme.Highlight) .Append($"Assemblies=", context.ColorScheme.Default) .Append($"{totalActiveAssemblies} ", context.ColorScheme.Highlight) .Append($"Pass="******"{totalPasses} ", context.ColorScheme.Success) .AppendIf(totalPasses == 0, $"{totalPasses} ", context.ColorScheme.Default) .Append($"Fail=", context.ColorScheme.Default) .AppendIf(totalFails > 0, $"{totalFails} ", context.ColorScheme.DarkError) .AppendIf(totalFails == 0, $"{totalFails} ", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"Ignored=", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"{totalIgnored} ", context.ColorScheme.DarkDefault) .Append($"Total=", context.ColorScheme.Default) .Append($"{totalTestsProcessed} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"of ", context.ColorScheme.Default) .AppendIf(context.TotalTestsQueued > 0, $"{context.TotalTestsQueued} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .AppendIf(context.TotalTestsQueued > 0, $"{((totalTestsProcessed / (double)context.TotalTestsQueued) * 100.0):F0}%", context.ColorScheme.DarkDuration) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.RightBracket}", context.ColorScheme.Bright) //.Append(context.Client.IsWaitingForConnection ? $"{UTF8Constants.LeftBracket}waiting{UTF8Constants.RightBracket}" : "", context.ColorScheme.DarkDuration) .AppendIf(!context.Console.IsOutputRedirected, (length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos + 1, DirectOutputMode.Static); // don't display this as often as its expensive to write if (_performFullDraw) { context.Console.SetCursorPosition(0, 2); var allCompletedAssemblies = context.EventLog .Where(x => x.Event.Event == EventNames.EndAssembly) .GroupBy(x => x.Event.TestSuite) .Select(x => x.FirstOrDefault()) .OrderByDescending(x => x.Event.Duration); var allPendingAssemblies = context.EventLog .Where(x => x.Event.Event == EventNames.StartAssembly && !allCompletedAssemblies.Select(y => y.Event.TestSuite).Contains(x.Event.TestSuite)) .GroupBy(x => x.Event.TestSuite) .Select(x => x.FirstOrDefault()) .OrderByDescending(x => x.DateAdded); var completedAssemblies = allCompletedAssemblies.Take(20); var pendingAssemblies = allPendingAssemblies.Take(20); var completedAssembliesBuilder = new ColorTextBuilder(); completedAssembliesBuilder.Append($"Completed Assemblies ", context.ColorScheme.Bright) .Append("[").Append($"{allCompletedAssemblies.Count()}", context.ColorScheme.Duration).Append("]") .AppendLine(); if (completedAssemblies.Any()) { foreach (var assembly in completedAssemblies) { var entryOutput = new ColorTextBuilder(); var completionTime = assembly.DateAdded; var duration = DateTime.Now.Subtract(assembly.Event.StartTime); if (assembly.Event.EndTime != DateTime.MinValue) { duration = assembly.Event.Duration; } var prettyTestName = DisplayUtil.GetPrettyTestName(assembly.Event.TestSuite, context.ColorScheme.DarkDefault, context.ColorScheme.Default, context.ColorScheme.DarkDefault, context.MaxTestCaseArgumentLength); // print out this test name and duration entryOutput .Append($"[{completionTime.ToString(TimeFormat)}] ", context.ColorScheme.DarkDuration) .Append(prettyTestName) .Append($" {duration.ToTotalElapsedTime()}", context.ColorScheme.Duration); completedAssembliesBuilder.AppendLine(entryOutput); } } var activeAssembliesBuilder = new ColorTextBuilder(); activeAssembliesBuilder.Append($"Running Assemblies", context.ColorScheme.Bright) .Append("[").Append($"{allPendingAssemblies.Count()}", context.ColorScheme.Duration).Append("]") .AppendLine(); if (pendingAssemblies.Any()) { foreach (var assembly in pendingAssemblies) { var entryOutput = new ColorTextBuilder(); var completionTime = assembly.DateAdded; var duration = DateTime.Now.Subtract(assembly.Event.StartTime); if (assembly.Event.EndTime != DateTime.MinValue) { duration = assembly.Event.Duration; } var prettyTestName = DisplayUtil.GetPrettyTestName(assembly.Event.TestSuite, context.ColorScheme.DarkDefault, context.ColorScheme.Default, context.ColorScheme.DarkDefault, context.MaxTestCaseArgumentLength); // print out this test name and duration entryOutput .Append(prettyTestName) .Append($" {duration.ToTotalElapsedTime()}", context.ColorScheme.Duration); activeAssembliesBuilder.AppendLine(entryOutput); } } // write builders side-by-side var columnSpacing = 2; var columnWidth = (context.Console.WindowWidth / 2) - (columnSpacing * 2); var output = completedAssembliesBuilder.Interlace(activeAssembliesBuilder, columnSpacing, columnWidth); context.Console.WriteLine(output); // output complete context.Console.SetCursorPosition(0, 0); } } }
public void Draw(ViewContext context, long ticks) { if (_startTicks == 0) { _startTicks = ticks; ClearScreen(context); } var yPos = context.BeginY; var drawChecksum = 0; var performDrawByTime = true; var performDrawByDataChange = true; var activeTestsCountChanged = context.ActiveTests.Count != context.LastNumberOfTestsRunning; var windowWidth = 160; var windowHeight = 40; if (!context.Console.IsOutputRedirected) { Console.CursorVisible = false; windowWidth = Console.WindowWidth; windowHeight = Console.WindowHeight; if (windowHeight != _previousWindowHeight) { ClearScreen(context); } _previousWindowHeight = windowHeight; } if (context.Console.IsOutputRedirected) { // if any tests have changed state based on checksum, allow a redraw drawChecksum = ComputeActiveTestChecksum(context); performDrawByTime = DateTime.Now.Subtract(context.LastDrawTime).TotalMilliseconds > context.DrawIntervalMilliseconds; performDrawByDataChange = drawChecksum != context.LastDrawChecksum; } if ((performDrawByTime || performDrawByDataChange)) { if (!context.Console.IsOutputRedirected) { WriteHeader(context); } // figure out how many tests we can fit on screen var maxActiveTestsToDisplay = context.Configuration.MaxActiveTestsToDisplay; if (!context.Console.IsOutputRedirected && maxActiveTestsToDisplay == 0) { maxActiveTestsToDisplay = Console.WindowHeight - yPos - 2 - context.Configuration.MaxFailedTestsToDisplay - 4; } context.LastDrawChecksum = drawChecksum; if (context.Console.IsOutputRedirected) { context.Console.WriteLine(); } else if (activeTestsCountChanged) { // number of tests changed var nextNumberOfTestsDrawn = Math.Min(context.ActiveTests.Count, maxActiveTestsToDisplay); if (nextNumberOfTestsDrawn < context.LastNumberOfTestsDrawn) { // clear the static display if we are displaying less tests than the previous draw if (!context.Console.IsOutputRedirected) { var startY = yPos + nextNumberOfTestsDrawn + 3; var endY = startY + (context.LastNumberOfTestsDrawn - nextNumberOfTestsDrawn); context.Console.ClearAtRange(0, startY, 0, endY); } } context.LastNumberOfTestsRunning = context.ActiveTests.Count; } var testNumber = 0; var totalActiveTests = context.ActiveTests.Count(x => !x.IsQueuedForRemoval); var totalActiveTestFixtures = context.ActiveTestFixtures.Count(x => !x.IsQueuedForRemoval); var totalActiveAssemblies = context.ActiveAssemblies.Count(x => !x.IsQueuedForRemoval); if (totalActiveTests > 0 && totalActiveTestFixtures == 0) { // fix for older versions of nUnit that don't send the start test fixture event // it will still be incorrect, as it will treat parents of tests with multiple cases as a testfixture var parentIds = context.ActiveTests .Where(x => !x.IsQueuedForRemoval && !string.IsNullOrEmpty(x.Event.ParentId)) .Select(x => x.Event.ParentId) .Distinct(); totalActiveTestFixtures = context.ActiveTestSuites.Count(x => !x.IsQueuedForRemoval && parentIds.Contains(x.Event.Id)); } var totalPasses = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Pass); var totalFails = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail); var totalIgnored = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Skipped); var totalTestsProcessed = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest); context.LastNumberOfLinesDrawn = 0; // write the summary of all test state context.Console.WriteAt(ColorTextBuilder.Create .Append("Tests state: ", context.ColorScheme.Bright) .Append($"Tests=", context.ColorScheme.Default) .Append($"{totalActiveTests} ", context.ColorScheme.Highlight) .Append($"Fixtures=", context.ColorScheme.Default) .Append($"{totalActiveTestFixtures} ", context.ColorScheme.Highlight) .Append($"Assemblies=", context.ColorScheme.Default) .Append($"{totalActiveAssemblies} ", context.ColorScheme.Highlight) .Append($"Pass="******"{totalPasses} ", context.ColorScheme.Success) .AppendIf(totalPasses == 0, $"{totalPasses} ", context.ColorScheme.Default) .Append($"Fail=", context.ColorScheme.Default) .AppendIf(totalFails > 0, $"{totalFails} ", context.ColorScheme.DarkError) .AppendIf(totalFails == 0, $"{totalFails} ", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"Ignored=", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"{totalIgnored} ", context.ColorScheme.DarkDefault) .Append($"Total=", context.ColorScheme.Default) .Append($"{totalTestsProcessed} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"of ", context.ColorScheme.Default) .AppendIf(context.TotalTestsQueued > 0, $"{context.TotalTestsQueued} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .AppendIf(context.TotalTestsQueued > 0, $"{((totalTestsProcessed / (double)context.TotalTestsQueued) * 100.0):F0}%", context.ColorScheme.DarkDuration) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.RightBracket}", context.ColorScheme.Bright) //.Append(context.Client.IsWaitingForConnection ? $"{UTF8Constants.LeftBracket}waiting{UTF8Constants.RightBracket}" : "", context.ColorScheme.DarkDuration) .AppendIf(!context.Console.IsOutputRedirected, (length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos, DirectOutputMode.Static); context.LastNumberOfLinesDrawn++; if (!context.Console.IsOutputRedirected) { context.Console.WriteAt(ColorTextBuilder.Create .Append("Runtime: ", context.ColorScheme.Bright) .Append($"{DateTime.Now.Subtract(context.StartTime).ToTotalElapsedTime()} ", context.ColorScheme.Duration) .Append((length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos + 1, DirectOutputMode.Static); context.LastNumberOfLinesDrawn++; } if (!context.Console.IsOutputRedirected && !string.IsNullOrEmpty(context.CurrentFrameworkVersion)) { context.Console.WriteAt(ColorTextBuilder.Create .Append($"{context.CurrentFrameworkVersion}", context.ColorScheme.DarkDuration) .AppendIf(!context.Console.IsOutputRedirected, (length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos + context.LastNumberOfLinesDrawn, DirectOutputMode.Static); context.LastNumberOfLinesDrawn++; } // ************************** // Draw Active Tests // ************************** IEnumerable <EventEntry> activeTestsToDisplay; if (context.Console.IsOutputRedirected) { // for log file output only show running tests activeTestsToDisplay = context.ActiveTests .Where(x => x.Event.TestStatus == TestStatus.Running && !x.IsQueuedForRemoval) .OrderByDescending(x => x.Elapsed); } else { activeTestsToDisplay = context.ActiveTests .OrderBy(x => x.Event.TestStatus) .ThenByDescending(x => x.Elapsed) .Take(maxActiveTestsToDisplay); } foreach (var test in activeTestsToDisplay) { testNumber++; var lifetime = DateTime.Now.Subtract(test.Event.StartTime); if (test.Event.EndTime != DateTime.MinValue) { lifetime = test.Event.Duration; } var testColor = context.ColorScheme.Highlight; var testStatus = "INVD"; switch (test.Event.TestStatus) { case TestStatus.Pass: testStatus = "PASS"; testColor = context.ColorScheme.Success; break; case TestStatus.Fail: testStatus = "FAIL"; testColor = context.ColorScheme.Error; break; case TestStatus.Skipped: testStatus = "SKIP"; testColor = context.ColorScheme.DarkDefault; break; case TestStatus.Running: default: testStatus = $"RUN{GetRunningAnimationStep(context)}"; testColor = context.ColorScheme.Highlight; break; } var testName = test.Event.TestName; // try to get the parent fixture if its available var testFixtureName = !string.IsNullOrEmpty(test.Event.ParentId) ? context.ActiveTestFixtures .Where(x => x.Event.Id == test.Event.ParentId) .Select(x => x.Event.TestSuite) .FirstOrDefault() : string.Empty; if (string.IsNullOrEmpty(testFixtureName)) { // if this is an older version of nUnit, try getting the parent suite name testFixtureName = !string.IsNullOrEmpty(test.Event.ParentId) ? context.ActiveTestSuites .Where(x => x.Event.Id == test.Event.ParentId) .Select(x => x.Event.TestSuite) .FirstOrDefault() : string.Empty; } var prettyTestName = DisplayUtil.GetPrettyTestName(testName, testFixtureName ?? string.Empty, context.ColorScheme.DarkDefault, context.ColorScheme.Default, context.ColorScheme.DarkDefault, context.MaxTestCaseArgumentLength); // print out this test name and duration context.Console.WriteAt(ColorTextBuilder.Create // test number .Append($"{testNumber}: ", context.ColorScheme.DarkDefault) // spaced in columns .AppendIf(testNumber < 10 && !context.Console.IsOutputRedirected, $" ") // test status if not logging to file .AppendIf(!context.Console.IsOutputRedirected, $"{UTF8Constants.LeftBracket}", context.ColorScheme.DarkDefault) .AppendIf(!context.Console.IsOutputRedirected, testStatus, testColor) .AppendIf(!context.Console.IsOutputRedirected, $"{UTF8Constants.RightBracket} ", context.ColorScheme.DarkDefault) // test name .Append(prettyTestName) // test duration .Append($" {lifetime.ToTotalElapsedTime()}", context.ColorScheme.Duration) // clear out the rest of the line .AppendIf((length) => !context.Console.IsOutputRedirected && length < windowWidth, (length) => DisplayUtil.Pad(windowWidth - length)) .Truncate(windowWidth), 0, yPos + context.LastNumberOfLinesDrawn, DirectOutputMode.Static); context.LastNumberOfLinesDrawn++; } context.LastNumberOfTestsDrawn = testNumber; IncrementRunningAnimationStep(context); // ************************** // Draw Test Failures // ************************** if (!context.Console.IsOutputRedirected && context.Configuration.MaxFailedTestsToDisplay > 0) { var failedTests = context.EventLog .Where(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail) .GroupBy(x => x.Event.TestName) .Select(x => x.FirstOrDefault()) .OrderByDescending(x => x.DateAdded) .Take(context.Configuration.MaxFailedTestsToDisplay); if (failedTests.Any()) { var totalFailedTests = failedTests.Count(); context.Console.WriteAt(ColorTextBuilder.Create.AppendLine($"Most Recent Failed Tests", context.ColorScheme.Error), 0, windowHeight - totalFailedTests - _bottomPadding - 1, DirectOutputMode.Static); var failedTestNumber = 0; foreach (var test in failedTests) { failedTestNumber++; var duration = DateTime.Now.Subtract(test.Event.StartTime); if (test.Event.EndTime != DateTime.MinValue) { duration = test.Event.Duration; } var prettyTestName = DisplayUtil.GetPrettyTestName(test.Event.FullName, context.ColorScheme.DarkDefault, context.ColorScheme.Default, context.ColorScheme.DarkDefault, context.MaxTestCaseArgumentLength); // print out this test name and duration context.Console.WriteAt(ColorTextBuilder.Create .Append($" {UTF8Constants.Bullet} ") .Append(prettyTestName) .Append($" {duration.ToTotalElapsedTime()}", context.ColorScheme.Duration) .Append($" {UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .Append("FAILED", context.ColorScheme.Error) .Append($"{UTF8Constants.RightBracket} ", context.ColorScheme.Bright) .Append($"{test.DateAdded.ToString(Constants.TimeFormat)}", context.ColorScheme.DarkDuration) // clear out the rest of the line .AppendIf((length) => !context.Console.IsOutputRedirected && length < windowWidth, (length) => DisplayUtil.Pad(windowWidth - length)) .Truncate(windowWidth), 0, windowHeight - totalFailedTests + failedTestNumber - _bottomPadding - 1, DirectOutputMode.Static); } } } } }
public void Draw(ViewContext context, long ticks) { if (_startTicks == 0) { _startTicks = ticks; ClearScreen(context); } if (!context.Console.IsOutputRedirected) { // if the user has scrolled the page don't perform any drawing if (Console.WindowTop > 0) { return; } Console.CursorVisible = false; _performFullDraw = (_startTicks - ticks) % DefaultTickWait == 0; var windowWidth = Console.WindowWidth; var windowHeight = Console.WindowHeight; if (windowHeight != _previousWindowHeight) { _performFullDraw = true; } _previousWindowHeight = windowHeight; if (_performFullDraw) { ClearScreen(context); } var yPos = 0; var totalActiveTests = context.ActiveTests.Count(x => !x.IsQueuedForRemoval); var totalActiveTestFixtures = context.ActiveTestFixtures.Count(x => !x.IsQueuedForRemoval); var totalActiveAssemblies = context.ActiveAssemblies.Count(x => !x.IsQueuedForRemoval); if (totalActiveTests > 0 && totalActiveTestFixtures == 0) { // fix for older versions of nUnit that don't send the start test fixture event // it will still be incorrect, as it will treat parents of tests with multiple cases as a testfixture var parentIds = context.ActiveTests .Where(x => !x.IsQueuedForRemoval && !string.IsNullOrEmpty(x.Event.ParentId)) .Select(x => x.Event.ParentId) .Distinct(); totalActiveTestFixtures = context.ActiveTestSuites.Count(x => !x.IsQueuedForRemoval && parentIds.Contains(x.Event.Id)); } var totalPasses = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Pass); var totalFails = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail); var totalIgnored = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Skipped); var totalTestsProcessed = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest); WriteHeader(context); // write the summary of all test state context.Console.WriteAt(ColorTextBuilder.Create .Append("Tests state: ", context.ColorScheme.Bright) .Append($"Tests=", context.ColorScheme.Default) .Append($"{totalActiveTests} ", context.ColorScheme.Highlight) .Append($"Fixtures=", context.ColorScheme.Default) .Append($"{totalActiveTestFixtures} ", context.ColorScheme.Highlight) .Append($"Assemblies=", context.ColorScheme.Default) .Append($"{totalActiveAssemblies} ", context.ColorScheme.Highlight) .Append($"Pass="******"{totalPasses} ", context.ColorScheme.Success) .AppendIf(totalPasses == 0, $"{totalPasses} ", context.ColorScheme.Default) .Append($"Fail=", context.ColorScheme.Default) .AppendIf(totalFails > 0, $"{totalFails} ", context.ColorScheme.DarkError) .AppendIf(totalFails == 0, $"{totalFails} ", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"Ignored=", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"{totalIgnored} ", context.ColorScheme.DarkDefault) .Append($"Total=", context.ColorScheme.Default) .Append($"{totalTestsProcessed} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"of ", context.ColorScheme.Default) .AppendIf(context.TotalTestsQueued > 0, $"{context.TotalTestsQueued} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .AppendIf(context.TotalTestsQueued > 0, $"{((totalTestsProcessed / (double)context.TotalTestsQueued) * 100.0):F0}%", context.ColorScheme.DarkDuration) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.RightBracket}", context.ColorScheme.Bright) //.Append(context.Client.IsWaitingForConnection ? $"{UTF8Constants.LeftBracket}waiting{UTF8Constants.RightBracket}" : "", context.ColorScheme.DarkDuration) .AppendIf(!context.Console.IsOutputRedirected, (length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos + 1, DirectOutputMode.Static); if (_performFullDraw) { // build a report var runContext = new RunContext(); var report = context.Commander.CreateReportFromHistory(false); runContext.Runs.Add(context.Commander.GenerateReportContext(false), new List <DataEvent> { report }); var reportWriter = new ReportWriter(context.Console, context.ColorScheme, context.Configuration, runContext, false); reportWriter.WriteFinalReport(); context.Console.SetCursorPosition(0, 0); } } }
public void Draw(ViewContext context, long ticks) { if (_startTicks == 0) { _startTicks = ticks; context.Console.Clear(); } if (!context.Console.IsOutputRedirected) { // if the user has scrolled the page don't perform any drawing if (Console.WindowTop > 0) { return; } Console.CursorVisible = false; _performFullDraw = (_startTicks - ticks) % DefaultTickWait == 0; var windowWidth = Console.WindowWidth; var windowHeight = Console.WindowHeight; if (windowHeight != _previousWindowHeight) { _performFullDraw = true; } _previousWindowHeight = windowHeight; if (_performFullDraw) { ClearScreen(context); } var lineSeparator = DisplayUtil.Pad(Console.WindowWidth - 1, UTF8Constants.HorizontalLine); var yPos = 0; WriteHeader(context); // figure out how many tests we can fit on screen var maxActiveTestsToDisplay = Console.WindowHeight - yPos - 2; var totalActive = context.ActiveTests.Count(x => !x.IsQueuedForRemoval); var totalPasses = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Pass); var totalFails = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail); var totalIgnored = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Skipped); var totalTestsProcessed = context.EventLog.Count(x => x.Event.Event == EventNames.EndTest); // write the summary of all test state context.Console.WriteAt(ColorTextBuilder.Create .Append("Tests state: ", context.ColorScheme.Bright) .Append($"Active=", context.ColorScheme.Default) .Append($"{totalActive} ", context.ColorScheme.Highlight) .Append($"Pass="******"{totalPasses} ", context.ColorScheme.Success) .AppendIf(totalPasses == 0, $"{totalPasses} ", context.ColorScheme.Default) .Append($"Fail=", context.ColorScheme.Default) .AppendIf(totalFails > 0, $"{totalFails} ", context.ColorScheme.DarkError) .AppendIf(totalFails == 0, $"{totalFails} ", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"Ignored=", context.ColorScheme.Default) .AppendIf(!context.Console.IsOutputRedirected, $"{totalIgnored} ", context.ColorScheme.DarkDefault) .Append($"Total=", context.ColorScheme.Default) .Append($"{totalTestsProcessed} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"of ", context.ColorScheme.Default) .AppendIf(context.TotalTestsQueued > 0, $"{context.TotalTestsQueued} ", context.ColorScheme.DarkDefault) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .AppendIf(context.TotalTestsQueued > 0, $"{((totalTestsProcessed / (double)context.TotalTestsQueued) * 100.0):F0}%", context.ColorScheme.DarkDuration) .AppendIf(context.TotalTestsQueued > 0, $"{UTF8Constants.RightBracket}", context.ColorScheme.Bright) //.Append(context.Client.IsWaitingForConnection ? $"{UTF8Constants.LeftBracket}waiting{UTF8Constants.RightBracket}" : "", context.ColorScheme.DarkDuration) .AppendIf(!context.Console.IsOutputRedirected, (length) => DisplayUtil.Pad(windowWidth - length)), 0, yPos + 1, DirectOutputMode.Static); var failedTests = context.EventLog .Where(x => x.Event.Event == EventNames.EndTest && x.Event.TestStatus == TestStatus.Fail) .GroupBy(x => x.Event.TestName) .Select(x => x.FirstOrDefault()) .OrderByDescending(x => x.DateAdded) .Take(context.Configuration.MaxFailedTestsToDisplay); context.Console.WriteAt(ColorTextBuilder.Create.AppendLine($"Failed Tests Report", context.ColorScheme.Error), 0, yPos + 2, DirectOutputMode.Static); if (!failedTests.Any()) { context.Console.WriteAt(ColorTextBuilder.Create.AppendLine($"There are no failed tests.", context.ColorScheme.Default), 0, yPos + 4, DirectOutputMode.Static); } else { // don't display this as often as its expensive to write if (_performFullDraw) { context.Console.SetCursorPosition(0, yPos + 5); foreach (var test in failedTests) { var testOutput = new ColorTextBuilder(); var errorTime = test.DateAdded; var duration = DateTime.Now.Subtract(test.Event.StartTime); if (test.Event.EndTime != DateTime.MinValue) { duration = test.Event.Duration; } var prettyTestName = DisplayUtil.GetPrettyTestName(test.Event.FullName, context.ColorScheme.DarkDefault, context.ColorScheme.Default, context.ColorScheme.DarkDefault, context.MaxTestCaseArgumentLength); // print out this test name and duration testOutput.Append(ColorTextBuilder.Create .Append($" {UTF8Constants.Bullet} ") .Append(prettyTestName) .Append($" {duration.ToTotalElapsedTime()}", context.ColorScheme.Duration) .Append($" {UTF8Constants.LeftBracket}", context.ColorScheme.Bright) .Append("FAILED", context.ColorScheme.Error) .Append($"{UTF8Constants.RightBracket}", context.ColorScheme.Bright) // clear out the rest of the line .AppendIf((length) => !context.Console.IsOutputRedirected && length < windowWidth, (length) => DisplayUtil.Pad(windowWidth - length)) .Truncate(windowWidth)); testOutput.Append(ColorTextBuilder.Create.Append(" Failed at: ", context.ColorScheme.Default).AppendLine($"{errorTime.ToString(Constants.TimeFormat)}", context.ColorScheme.DarkDuration)); // print out errors if (!string.IsNullOrEmpty(test.Event.ErrorMessage)) { testOutput.AppendLine($" Error Output: ", context.ColorScheme.Bright); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); if (!context.Configuration.DontPrettify) { testOutput.Append(ErrorEncoding.Format(test.Event.ErrorMessage, context.ColorScheme)); } else { testOutput.Append(test.Event.ErrorMessage); } testOutput.AppendLine(); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); } if (!string.IsNullOrEmpty(test.Event.StackTrace)) { testOutput.AppendLine($" Stack Trace:", context.ColorScheme.Bright); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); if (!context.Configuration.DontPrettify) { testOutput.Append(StackTracePrettify.Format(test.Event.StackTrace, context.ColorScheme)); } else { testOutput.Append(test.Event.StackTrace); } testOutput.AppendLine(); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); } if (!string.IsNullOrEmpty(test.Event.TestOutput)) { testOutput.AppendLine($" Test Output: ", context.ColorScheme.Bright); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); if (!context.Configuration.DontPrettify) { testOutput.Append(ErrorEncoding.Format(test.Event.TestOutput, context.ColorScheme)); } else { testOutput.Append(test.Event.TestOutput); } testOutput.AppendLine(); testOutput.AppendLine(lineSeparator, context.ColorScheme.DarkDefault); } testOutput.AppendLine(); testOutput.AppendLine(); context.Console.WriteLine(testOutput); } context.Console.SetCursorPosition(0, 0); } } } }