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; 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); } } } }