XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.XUnit

【DLL】提供方便快捷的测试,无需编写Main方法,可直接添加特性在类或方法上进行测试

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using XFEExtension.NetCore.XUnit.Runtime;

namespace XFEExtension.NetCore.XUnit.Reporting;

internal sealed class ConsolePresenter(ConsoleLocalizer text)
{
    public static void ConfigureConsole()
    {
        try
        {
            if (Console.OutputEncoding.CodePage != Encoding.UTF8.CodePage)
                Console.OutputEncoding = new UTF8Encoding(false);
        }
        catch
        {
        }
    }

    public void PrintHeader(bool runTests, bool runBenchmarks, int testCount, int benchmarkCount, XfeRunSettings settings)
    {
        var version = typeof(ConsolePresenter).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
            .Split('+')[0] ?? typeof(ConsolePresenter).Assembly.GetName().Version?.ToString(3) ?? "4.0.0";
        var mode = runTests && runBenchmarks
            ? text.Select("Tests + benchmarks", "测试 + 基准")
            : runBenchmarks ? text.Select("Benchmarks", "性能基准") : text.Select("Tests", "普通测试");
        var testDescription = text.Select($"{testCount} {(testCount == 1 ? "test" : "tests")}", $"{testCount} 个测试");
        var benchmarkDescription = text.Select($"{benchmarkCount} {(benchmarkCount == 1 ? "benchmark" : "benchmarks")}", $"{benchmarkCount} 个基准");
        var discovered = runTests && runBenchmarks
            ? text.Select($"{testDescription}, {benchmarkDescription}", $"{testDescription},{benchmarkDescription}")
            : runBenchmarks ? benchmarkDescription : testDescription;
        var parallelism = settings.Tests.Parallel
            ? text.Select($"On ({settings.Tests.MaxParallelism} workers)", $"启用({settings.Tests.MaxParallelism} 个工作线程)")
            : text.Select("Off", "关闭");

        WriteTitle($"XFE Test Runner {version}");
        var metadata = new List<(string Label, string Value)>
        {
            (text.Select("Mode", "模式"), mode),
            (text.Select("Runtime", "运行时"), RuntimeInformation.FrameworkDescription),
            (text.Select("Language", "语言"), text.LanguageName),
            (text.Select("Platform", "平台"), $"{RuntimeInformation.OSDescription} · {RuntimeInformation.ProcessArchitecture}"),
            (text.Select("Discovered", "已发现"), discovered)
        };
        if (runTests)
            metadata.Add((text.Select("Parallel", "并行"), parallelism));
        else if (runBenchmarks)
            metadata.Add((
                text.Select("Job", "作业"),
                text.Select(
                    $"{settings.Benchmark.TargetIterationMilliseconds} ms target · {settings.Benchmark.MinIterationCount}-{settings.Benchmark.MaxIterationCount} samples",
                    $"目标 {settings.Benchmark.TargetIterationMilliseconds} ms · {settings.Benchmark.MinIterationCount}-{settings.Benchmark.MaxIterationCount} 个样本")));
        WriteMetadataGrid(metadata);
        WriteRule('╰', '─', '╯');
        Console.WriteLine();
    }

    public void PrintList(IReadOnlyList<TestDescriptor> tests, IReadOnlyList<BenchmarkDescriptor> benchmarks)
    {
        var itemCount = tests.Count + benchmarks.Count;
        WriteSection(text.Select("Discovered work", "发现的项目"), text.Select($"{itemCount} {(itemCount == 1 ? "item" : "items")}", $"{itemCount} 项"));
        foreach (var test in tests)
            WriteListItem(text.Select("TEST", "测试"), test.Id, test.DisplayName, ConsoleColor.Cyan);
        foreach (var benchmark in benchmarks)
            WriteListItem(text.Select("BENCH", "基准"), benchmark.Id, benchmark.DisplayName, ConsoleColor.Magenta);
        if (tests.Count == 0 && benchmarks.Count == 0)
            WriteColoredLine(text.Select("  No work matched the current filters.", "  没有项目符合当前筛选条件。"), ConsoleColor.Yellow);
        Console.WriteLine();
        var testDescription = text.Select($"{tests.Count} {(tests.Count == 1 ? "test" : "tests")}", $"{tests.Count} 个测试");
        var benchmarkDescription = text.Select($"{benchmarks.Count} {(benchmarks.Count == 1 ? "benchmark" : "benchmarks")}", $"{benchmarks.Count} 个基准");
        WriteColoredLine(text.Select($"Total: {testDescription}, {benchmarkDescription}", $"总计:{testDescription},{benchmarkDescription}"), ConsoleColor.DarkGray);
    }

    public void PrintTests(TestRunSummary summary)
    {
        var legacySingleRuns = summary.Results.Where(static result => result.IsLegacySingleRun).ToArray();
        if (legacySingleRuns.Length > 0)
        {
            WriteSection(text.Select("SMTest single-run output", "SMTest 单次执行输出"), text.Select($"{legacySingleRuns.Length} methods", $"{legacySingleRuns.Length} 个方法"));
            for (var index = 0; index < legacySingleRuns.Length; index++)
                PrintLegacySingleRun(legacySingleRuns[index], index + 1);
            Console.WriteLine();
        }

        WriteSection(text.Select("Test results", "测试结果"), text.Select($"{summary.Total} {(summary.Total == 1 ? "test" : "tests")}", $"{summary.Total} 个测试"));
        if (summary.Results.Count == 0)
        {
            WriteColoredLine(text.Select("  No tests matched the current filters.", "  没有测试符合当前筛选条件。"), ConsoleColor.Yellow);
            Console.WriteLine();
            PrintTestSummary(summary);
            return;
        }

        var consoleWidth = SafeConsoleWidth();
        const int statusWidth = 10;
        const int durationWidth = 14;
        var nameWidth = Math.Max(20, consoleWidth - statusWidth - durationWidth - 4);
        var headers = new[]
        {
            text.Select("Status", "状态"),
            text.Select("Test", "测试"),
            text.Select("Duration", "耗时")
        };
        WriteTestRow(headers[0], headers[1], headers[2], statusWidth, nameWidth, durationWidth, ConsoleColor.Cyan, false);
        WriteTableRule([statusWidth, nameWidth, durationWidth]);

        foreach (var result in summary.Results)
        {
            var color = OutcomeColor(result.Outcome);
            var duration = result.Outcome == TestOutcome.Skipped ? "—" : FormatDuration(result.TotalDuration);
            WriteTestRow(text.Outcome(result.Outcome), result.DisplayName, duration, statusWidth, nameWidth, durationWidth, color, true);

            if (!string.IsNullOrWhiteSpace(result.Message))
            {
                var label = result.Outcome == TestOutcome.Skipped ? text.Select("Reason", "原因") : text.Select("Message", "消息");
                WriteDetail(label, text.Message(result.Message), result.Outcome == TestOutcome.Skipped ? ConsoleColor.DarkYellow : ConsoleColor.Red);
            }
            if (result.Attempts > 1)
                WriteDetail(text.Select("Attempts", "尝试次数"), result.Attempts.ToString(), ConsoleColor.DarkYellow);
            if (result.Outcome != TestOutcome.Passed && !result.IsLegacySingleRun && !string.IsNullOrWhiteSpace(result.Output))
                WriteBlock(text.Select("Captured output", "捕获的输出"), result.Output, ConsoleColor.DarkGray);
            if (result.Outcome is TestOutcome.Failed or TestOutcome.TimedOut or TestOutcome.Crashed && !string.IsNullOrWhiteSpace(result.StackTrace))
                WriteBlock(text.Select("Stack trace", "堆栈跟踪"), result.StackTrace, ConsoleColor.DarkGray);
        }

        Console.WriteLine();
        PrintTestSummary(summary);
        PrintSlowestTests(summary);
    }

    private void PrintLegacySingleRun(TestCaseResult result, int executionIndex)
    {
        var width = SafeConsoleWidth();
        var typeName = result.TypeName?.Split('.').LastOrDefault() ?? text.Select("Unknown type", "未知类型");
        var methodName = result.MethodName ?? result.DisplayName;
        var defaultName = $"{typeName}.{methodName}";
        var usesCustomName = !result.DisplayName.StartsWith(defaultName, StringComparison.Ordinal);
        var title = usesCustomName
            ? text.Select($"Name: {result.DisplayName}", $"标识名:{result.DisplayName}")
            : text.Select($"Method: {methodName}", $"方法名:{methodName}");
        title = TruncateDisplay(title, Math.Max(10, width - 8));
        var titlePrefix = $"╭─ {title} ";
        WriteColored(titlePrefix, ConsoleColor.DarkYellow);
        WriteColoredLine(new string('─', Math.Max(1, width - DisplayWidth(titlePrefix) - 1)) + "╮", ConsoleColor.DarkYellow);

        WriteColored("│ ", ConsoleColor.DarkYellow);
        WriteBadge(text.Select("START", "开始执行"), 12, ConsoleColor.Cyan);
        WriteColored($"  {text.Select("Method", "方法")}  ", ConsoleColor.DarkGray);
        WriteColored(methodName, ConsoleColor.Yellow);
        WriteColored($"  {text.Select("Class", "类")}  ", ConsoleColor.DarkGray);
        WriteColoredLine(typeName, ConsoleColor.Green);
        WriteColoredLine("│", ConsoleColor.DarkYellow);

        if (!string.IsNullOrEmpty(result.Output))
        {
            Console.Write(result.Output);
            if (!result.Output.EndsWith('\n'))
                Console.WriteLine();
        }

        WriteColoredLine("│", ConsoleColor.DarkYellow);
        WriteColored("│ ", ConsoleColor.DarkYellow);
        WriteBadge(text.Select("FINISHED", "执行完成"), 12, ConsoleColor.Cyan);
        WriteColored($"  {text.Select("Run", "执行批次")}  ", ConsoleColor.DarkGray);
        WriteColored(executionIndex.ToString(), ConsoleColor.Gray);
        WriteColored($"  {text.Select("Duration", "执行时间")}  ", ConsoleColor.DarkGray);
        WriteColoredLine(FormatDuration(result.BodyDuration), ConsoleColor.Cyan);

        WriteColored("│ ", ConsoleColor.DarkYellow);
        var passed = result.Outcome == TestOutcome.Passed;
        WriteBadge(passed ? text.Select("PASSED", "测试通过") : text.Select("FAILED", "测试失败"), 12, passed ? ConsoleColor.Green : ConsoleColor.Red);
        if (!passed && !string.IsNullOrWhiteSpace(result.Message))
        {
            WriteColored($"  {text.Select("Reason", "失败原因")}  ", ConsoleColor.Red);
            WriteColoredLine(text.Message(result.Message), ConsoleColor.Gray);
        }
        else
        {
            Console.WriteLine();
        }
        WriteColoredLine("╰" + new string('─', Math.Max(1, width - 2)) + "╯", ConsoleColor.DarkYellow);
    }

    public void PrintBenchmarks(BenchmarkRunSummary summary)
    {
        WriteSection(text.Select("Benchmark results", "基准结果"), text.Select($"{summary.Benchmarks.Count} {(summary.Benchmarks.Count == 1 ? "benchmark" : "benchmarks")}", $"{summary.Benchmarks.Count} 个基准"));
        if (summary.Benchmarks.Count == 0)
        {
            WriteColoredLine(text.Select("  No benchmarks matched the current filters.", "  没有基准符合当前筛选条件。"), ConsoleColor.Yellow);
            return;
        }

        var environment = summary.Benchmarks[0].Environment;
        WriteMetadata(text.Select("Environment", "环境"), $"{environment.Framework} · {environment.Architecture} · {environment.ProcessorCount} CPUs", "  ");
        WriteMetadata(text.Select("Clock", "计时器"), $"{environment.StopwatchFrequency:N0} Hz", "  ");
        Console.WriteLine();

        var consoleWidth = SafeConsoleWidth();
        var detailedTable = consoleWidth >= 120;
        var nameWidth = detailedTable ? Math.Clamp(consoleWidth - 98, 22, 52) : Math.Max(20, consoleWidth - 47);
        var widths = detailedTable
            ? new[] { nameWidth, 11, 11, 11, 11, 11, 12, 7, 8 }
            : new[] { nameWidth, 12, 12, 7, 8 };
        var headers = detailedTable
            ? new[]
            {
                text.Select("Benchmark", "基准"),
                text.Select("Mean", "均值"),
                text.Select("Error", "误差"),
                text.Select("StdDev", "标准差"),
                text.Select("Median", "中位数"),
                "P95",
                text.Select("Allocated/op", "分配/次"),
                text.Select("Ratio", "比率"),
                text.Select("Result", "状态")
            }
            : new[]
            {
                text.Select("Benchmark", "基准"),
                text.Select("Mean", "均值"),
                text.Select("Allocated/op", "分配/次"),
                text.Select("Ratio", "比率"),
                text.Select("Result", "状态")
            };
        WriteTableRow(headers, widths, ConsoleColor.Cyan);
        WriteTableRule(widths);
        foreach (var benchmark in summary.Benchmarks)
        {
            var status = benchmark.Warnings.Count == 0
                ? text.Select("OK", "正常")
                : text.Select("WARN", "警告");
            var values = detailedTable
                ? new[]
                {
                    benchmark.DisplayName,
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.MeanNanoseconds),
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.ErrorNanoseconds),
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.StandardDeviationNanoseconds),
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.MedianNanoseconds),
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.P95Nanoseconds),
                    FormatBytes(benchmark.Gc.AllocatedBytesPerOperation),
                    benchmark.BaselineRatio?.ToString("F3") ?? "-",
                    status
                }
                : new[]
                {
                    benchmark.DisplayName,
                    BuiltInReporters.FormatNanoseconds(benchmark.Statistics.MeanNanoseconds),
                    FormatBytes(benchmark.Gc.AllocatedBytesPerOperation),
                    benchmark.BaselineRatio?.ToString("F3") ?? "-",
                    status
                };
            WriteTableRow(values, widths, benchmark.Warnings.Count == 0 ? ConsoleColor.Gray : ConsoleColor.Yellow);
        }

        foreach (var benchmark in summary.Benchmarks.Where(static benchmark => benchmark.Warnings.Count > 0))
        {
            Console.WriteLine();
            WriteColoredLine($"  [!] {benchmark.DisplayName}", ConsoleColor.Yellow);
            foreach (var warning in benchmark.Warnings)
                Console.WriteLine($"    {text.Warning(warning)}");
        }

        Console.WriteLine();
        var convergence = summary.Benchmarks.Count(static benchmark => benchmark.Statistics.Converged);
        var resultText = summary.RegressionDetected
            ? text.Select("Performance regression detected", "检测到性能回归")
            : text.Select("No gated regression detected", "未检测到门禁性能回归");
        WriteSection(text.Select("Benchmark summary", "基准汇总"));
        WriteColored($"  {PadDisplay(text.Select("Result", "结果"), 14)}", ConsoleColor.DarkGray);
        WriteBadge(summary.RegressionDetected ? text.Select("FAILED", "回归") : text.Select("PASSED", "通过"), 10,
            summary.RegressionDetected ? ConsoleColor.Red : ConsoleColor.Green);
        Console.Write("    ");
        WriteColoredLine(resultText, summary.RegressionDetected ? ConsoleColor.Red : ConsoleColor.Green);
        WriteColored($"  {PadDisplay(text.Select("Benchmarks", "基准"), 14)}", ConsoleColor.DarkGray);
        WriteColored(text.Select($"{summary.Benchmarks.Count} total", $"总计 {summary.Benchmarks.Count}"), ConsoleColor.White);
        Console.Write("    ");
        WriteColored(text.Select($"{convergence} converged", $"已收敛 {convergence}"), ConsoleColor.Green);
        Console.Write("    ");
        WriteColoredLine(text.Select($"Duration  {FormatDuration(summary.Duration)}", $"用时  {FormatDuration(summary.Duration)}"), ConsoleColor.White);
    }

    public void PrintArtifacts(string path)
    {
        Console.WriteLine();
        WriteSection(text.Select("Artifacts", "报告产物"));
        WriteColoredLine($"  {Path.GetFullPath(path)}", ConsoleColor.DarkGray);
    }

    public void PrintHelp()
    {
        WriteTitle("XFE Test Runner 4.0");
        WriteMetadataGrid([(text.Select("Usage", "用法"), text.Select("<test application> [options]", "<测试程序> [选项]"))]);
        WriteRule('╰', '─', '╯');
        Console.WriteLine();
        WriteHelpSection(text.Select("Run selection", "运行选择"),
            ("--tests", text.Select("Run tests only (default).", "仅运行普通测试(默认)。")),
            ("--benchmarks", text.Select("Run benchmarks only.", "仅运行性能基准。")),
            ("--all", text.Select("Run tests and benchmarks.", "运行测试和性能基准。")),
            ("--list", text.Select("List discovered work without running it.", "列出发现的项目但不执行。")),
            ("--filter <text>", text.Select("Filter by id or display name.", "按标识或显示名称筛选。")),
            ("--category <name>", text.Select("Filter by category.", "按分类筛选。")));
        WriteHelpSection(text.Select("Execution", "执行控制"),
            ("--parallel | --no-parallel", text.Select("Enable or disable parallel test classes.", "启用或关闭测试类并行。")),
            ("--max-parallel <count>", text.Select("Set maximum test parallelism.", "设置测试最大并行数。")),
            ("--fail-fast", text.Select("Stop a group after its first failure.", "同组首次失败后停止。")),
            ("--explicit", text.Select("Include explicit tests.", "包含显式测试。")),
            ("--seed <number>", text.Select("Use a stable randomized test order.", "使用稳定的随机测试顺序。")),
            ("--quick", text.Select("Use the short benchmark job.", "使用短程基准作业。")));
        WriteHelpSection(text.Select("Interface and reports", "界面与报告"),
            ("--language <auto|en|zh>", text.Select("Select UI language; auto falls back to English.", "选择界面语言;自动模式无法识别时回退英文。")),
            ("--settings <path>", text.Select("Load a runsettings JSON file.", "加载 runsettings JSON 文件。")),
            ("--report <formats>", text.Select("Select json,junit,markdown,csv or none.", "选择 json、junit、markdown、csv 或 none。")),
            ("--artifacts <path>", text.Select("Set the report output directory.", "设置报告输出目录。")),
            ("--help", text.Select("Show this help.", "显示此帮助。")),
            ("--version", text.Select("Show runner version.", "显示运行器版本。")));
        WriteHelpSection(text.Select("Performance gate", "性能门禁"),
            ("--baseline <path>", text.Select("Load a benchmark JSON baseline.", "加载基准 JSON 基线。")),
            ("--max-regression <fraction>", text.Select("Set the allowed regression, for example 0.05.", "设置允许的回归比例,例如 0.05。")),
            ("--allow-environment-mismatch", text.Select("Allow gating across different environments.", "允许在不同环境间执行门禁。")));
    }

    public void PrintVersion()
    {
        var version = typeof(ConsolePresenter).Assembly.GetName().Version?.ToString(3) ?? "4.0.0";
        Console.WriteLine($"XFE Test Runner {version}");
    }

    public void PrintError(string message)
    {
        WriteColored(text.Select("Error: ", "错误:"), ConsoleColor.Red, Console.Error);
        Console.Error.WriteLine(text.Message(message));
    }

    public void PrintCancellation() => WriteColoredLine(text.Select("Run cancelled.", "运行已取消。"), ConsoleColor.Yellow, Console.Error);

    private void PrintTestSummary(TestRunSummary summary)
    {
        WriteSection(text.Select("Run summary", "运行汇总"));
        var executed = summary.Passed + summary.Failed;
        var successRate = executed == 0 ? 0d : summary.Passed * 100d / executed;
        var resultLabel = summary.Failed == 0 ? text.Select("PASSED", "通过") : text.Select("FAILED", "失败");

        WriteColored($"  {PadDisplay(text.Select("Result", "结果"), 14)}", ConsoleColor.DarkGray);
        WriteBadge(resultLabel, 10, summary.Failed == 0 ? ConsoleColor.Green : ConsoleColor.Red);
        Console.Write("    ");
        WriteColored(text.Select($"Duration  {FormatDuration(summary.Duration)}", $"用时  {FormatDuration(summary.Duration)}"), ConsoleColor.White);
        Console.WriteLine();

        WriteColored($"  {PadDisplay(text.Select("Tests", "测试"), 14)}", ConsoleColor.DarkGray);
        WriteColored(text.Select($"{summary.Total} total", $"总计 {summary.Total}"), ConsoleColor.White);
        Console.Write("    ");
        WriteColored(text.Select($"{summary.Passed} passed", $"通过 {summary.Passed}"), ConsoleColor.Green);
        Console.Write("    ");
        WriteColored(text.Select($"{summary.Failed} failed", $"失败 {summary.Failed}"), summary.Failed == 0 ? ConsoleColor.DarkGray : ConsoleColor.Red);
        Console.Write("    ");
        WriteColoredLine(text.Select($"{summary.Skipped} skipped", $"跳过 {summary.Skipped}"), ConsoleColor.Yellow);

        var barWidth = Math.Clamp(SafeConsoleWidth() - 36, 20, 48);
        var filled = executed == 0 ? 0 : Math.Clamp((int)Math.Round(barWidth * successRate / 100d), 0, barWidth);
        WriteColored($"  {PadDisplay(text.Select("Success rate", "成功率"), 14)}", ConsoleColor.DarkGray);
        WriteColored("[", ConsoleColor.DarkGray);
        WriteColored(new string('█', filled), summary.Failed == 0 ? ConsoleColor.Green : ConsoleColor.Yellow);
        WriteColored(new string('·', barWidth - filled), ConsoleColor.DarkGray);
        WriteColored("]", ConsoleColor.DarkGray);
        WriteColoredLine($"  {successRate:F1}%", summary.Failed == 0 ? ConsoleColor.Green : ConsoleColor.Yellow);
    }

    private void PrintSlowestTests(TestRunSummary summary)
    {
        var slowest = summary.Results
            .Where(static result => result.Outcome != TestOutcome.Skipped)
            .OrderByDescending(static result => result.TotalDuration)
            .Take(3)
            .ToArray();
        if (slowest.Length == 0)
            return;

        Console.WriteLine();
        WriteColoredLine(text.Select("  Slowest tests", "  最慢测试"), ConsoleColor.DarkCyan);
        var nameWidth = Math.Max(20, SafeConsoleWidth() - 24);
        for (var index = 0; index < slowest.Length; index++)
        {
            WriteColored($"  {index + 1}. ", ConsoleColor.DarkGray);
            WriteColored(PadDisplay(TruncateDisplay(slowest[index].DisplayName, nameWidth), nameWidth), ConsoleColor.Gray);
            WriteColoredLine(PadLeftDisplay(FormatDuration(slowest[index].TotalDuration), 16), ConsoleColor.DarkGray);
        }
    }

    private void WriteTitle(string title)
    {
        var width = SafeConsoleWidth();
        var suffixLength = Math.Max(1, width - DisplayWidth(title) - 5);
        WriteColored($"╭─ {title} ", ConsoleColor.Cyan);
        WriteColoredLine(new string('─', suffixLength) + "╮", ConsoleColor.DarkCyan);
    }

    private static void WriteMetadata(string label, string value, string indent = "│ ")
    {
        Console.Write(indent);
        WriteColored(PadDisplay(label, 12), ConsoleColor.DarkGray);
        WriteColoredLine(value, ConsoleColor.White);
    }

    private static void WriteMetadataGrid(IReadOnlyList<(string Label, string Value)> metadata)
    {
        var width = SafeConsoleWidth();
        if (width < 120)
        {
            foreach (var item in metadata)
                WriteMetadataBoxRow(item, null, width);
            return;
        }

        for (var index = 0; index < metadata.Count; index += 2)
            WriteMetadataBoxRow(metadata[index], index + 1 < metadata.Count ? metadata[index + 1] : null, width);
    }

    private static void WriteMetadataBoxRow((string Label, string Value) left, (string Label, string Value)? right, int width)
    {
        var contentWidth = width - 4;
        Console.Write("│ ");
        if (right.HasValue)
        {
            var leftWidth = (contentWidth - 3) / 2;
            var rightWidth = contentWidth - 3 - leftWidth;
            WriteMetadataCell(left, leftWidth);
            WriteColored(" │ ", ConsoleColor.DarkCyan);
            WriteMetadataCell(right.Value, rightWidth);
        }
        else
        {
            WriteMetadataCell(left, contentWidth);
        }
        Console.WriteLine(" │");
    }

    private static void WriteMetadataCell((string Label, string Value) item, int width)
    {
        const int labelWidth = 12;
        var valueWidth = Math.Max(1, width - labelWidth);
        WriteColored(PadDisplay(TruncateDisplay(item.Label, labelWidth), labelWidth), ConsoleColor.DarkGray);
        WriteColored(PadDisplay(TruncateDisplay(item.Value, valueWidth), valueWidth), ConsoleColor.White);
    }

    private void WriteSection(string title, string? suffix = null)
    {
        var heading = suffix is null ? title : $"{title} · {suffix}";
        heading = TruncateDisplay(heading, Math.Max(10, SafeConsoleWidth() - 5));
        var prefix = $"── {heading} ";
        WriteColored(prefix, ConsoleColor.Cyan);
        WriteColoredLine(new string('─', Math.Max(1, SafeConsoleWidth() - DisplayWidth(prefix))), ConsoleColor.DarkCyan);
    }

    private void WriteListItem(string kind, string id, string displayName, ConsoleColor color)
    {
        WriteBadge(kind, 9, color);
        Console.Write("  ");
        WriteColored(displayName, ConsoleColor.White);
        WriteColoredLine($"  {id}", ConsoleColor.DarkGray);
    }

    private static void WriteDetail(string label, string value, ConsoleColor color)
    {
        Console.Write(new string(' ', 12));
        WriteColored($"└─ {label}  ", color);
        WriteColoredLine(value, ConsoleColor.Gray);
    }

    private static void WriteBlock(string label, string value, ConsoleColor color)
    {
        var indent = new string(' ', 12);
        WriteColoredLine($"{indent}└─ {label}", color);
        foreach (var line in value.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n'))
            WriteColoredLine($"{indent}   {line}", ConsoleColor.DarkGray);
    }

    private static void WriteHelpSection(string title, params (string Option, string Description)[] items)
    {
        WriteColoredLine(title, ConsoleColor.Cyan);
        foreach (var item in items)
        {
            Console.Write("  ");
            WriteColored(PadDisplay(item.Option, 34), ConsoleColor.White);
            Console.WriteLine(item.Description);
        }
        Console.WriteLine();
    }

    private static void WriteTestRow(string status, string name, string duration, int statusWidth, int nameWidth, int durationWidth, ConsoleColor color, bool badge)
    {
        if (badge)
            WriteBadge(status, statusWidth, color);
        else
            WriteColored(PadDisplay(status, statusWidth), color);
        Console.Write("  ");
        WriteColored(PadDisplay(TruncateDisplay(name, nameWidth), nameWidth), badge ? ConsoleColor.Gray : color);
        Console.Write("  ");
        WriteColoredLine(PadLeftDisplay(duration, durationWidth), badge ? ConsoleColor.DarkGray : color);
    }

    private static void WriteBadge(string value, int width, ConsoleColor color)
    {
        var innerWidth = Math.Max(1, width - 2);
        var content = CenterDisplay(TruncateDisplay(value, innerWidth), innerWidth);
        WriteColored($"[{content}]", color);
    }

    private static void WriteTableRow(IReadOnlyList<string> values, IReadOnlyList<int> widths, ConsoleColor color)
    {
        for (var index = 0; index < values.Count; index++)
        {
            if (index > 0)
                Console.Write("  ");
            WriteColored(PadDisplay(TruncateDisplay(values[index], widths[index]), widths[index]), color);
        }
        Console.WriteLine();
    }

    private static void WriteTableRule(IReadOnlyList<int> widths)
    {
        for (var index = 0; index < widths.Count; index++)
        {
            if (index > 0)
                Console.Write("──");
            Console.Write(new string('─', widths[index]));
        }
        Console.WriteLine();
    }

    private static void WriteRule(char left, char fill, char right)
    {
        Console.Write(left);
        Console.Write(new string(fill, Math.Max(1, SafeConsoleWidth() - 2)));
        Console.WriteLine(right);
    }

    private static ConsoleColor OutcomeColor(TestOutcome outcome) => outcome switch
    {
        TestOutcome.Passed => ConsoleColor.Green,
        TestOutcome.Skipped => ConsoleColor.Yellow,
        _ => ConsoleColor.Red
    };

    private static string FormatDuration(TimeSpan duration)
    {
        if (duration.TotalMilliseconds < 0.001)
            return $"{duration.TotalNanoseconds:F0} ns";
        if (duration.TotalMilliseconds < 1)
            return $"{duration.TotalMicroseconds:F2} μs";
        if (duration.TotalSeconds < 1)
            return $"{duration.TotalMilliseconds:F3} ms";
        return $"{duration.TotalSeconds:F3} s";
    }

    private static string FormatBytes(double bytes)
    {
        if (bytes >= 1024 * 1024)
            return $"{bytes / (1024 * 1024):F2} MiB";
        if (bytes >= 1024)
            return $"{bytes / 1024:F2} KiB";
        return $"{bytes:F2} B";
    }

    private static int SafeConsoleWidth()
    {
        try
        {
            var width = Console.WindowWidth;
            return width > 0 ? Math.Clamp(width - 1, 72, 200) : 120;
        }
        catch
        {
            return 120;
        }
    }

    private static int DisplayWidth(string value) => value.Sum(static character => character >= 0x2E80 ? 2 : 1);

    private static string PadDisplay(string value, int width)
    {
        var padding = Math.Max(0, width - DisplayWidth(value));
        return value + new string(' ', padding);
    }

    private static string PadLeftDisplay(string value, int width)
    {
        var padding = Math.Max(0, width - DisplayWidth(value));
        return new string(' ', padding) + value;
    }

    private static string CenterDisplay(string value, int width)
    {
        var padding = Math.Max(0, width - DisplayWidth(value));
        var left = padding / 2;
        return new string(' ', left) + value + new string(' ', padding - left);
    }

    private static string TruncateDisplay(string value, int width)
    {
        if (DisplayWidth(value) <= width)
            return value;
        var result = new System.Text.StringBuilder();
        var currentWidth = 0;
        foreach (var character in value)
        {
            var characterWidth = character >= 0x2E80 ? 2 : 1;
            if (currentWidth + characterWidth > width - 1)
                break;
            result.Append(character);
            currentWidth += characterWidth;
        }
        return result + "…";
    }

    private static void WriteColored(string value, ConsoleColor color, TextWriter? writer = null)
    {
        writer ??= Console.Out;
        var redirected = ReferenceEquals(writer, Console.Error) ? Console.IsErrorRedirected : Console.IsOutputRedirected;
        if (redirected || !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NO_COLOR")))
        {
            writer.Write(value);
            return;
        }
        var original = Console.ForegroundColor;
        try
        {
            Console.ForegroundColor = color;
            writer.Write(value);
        }
        finally
        {
            Console.ForegroundColor = original;
        }
    }

    private static void WriteColoredLine(string value, ConsoleColor color, TextWriter? writer = null)
    {
        WriteColored(value, color, writer);
        (writer ?? Console.Out).WriteLine();
    }
}