From 080ac7afb33e63a6fee9273a1ed52d642aaa565e Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:51:38 +0100 Subject: [PATCH] breaking: remove CLI `verbosity` switch and re-use existing MTP `output` switch --- .../VerbosityCommandProvider.cs | 81 -------------- .../TestApplicationBuilderExtensions.cs | 5 +- .../Framework/TUnitServiceProvider.cs | 2 +- TUnit.Engine/Logging/TUnitVerbosity.cs | 56 ---------- TUnit.Engine/Services/VerbosityService.cs | 101 +++++++++++------- TUnit.Engine/TUnitMessageBus.cs | 1 + docs/docs/reference/command-line-flags.md | 19 ++-- 7 files changed, 78 insertions(+), 187 deletions(-) delete mode 100644 TUnit.Engine/CommandLineProviders/VerbosityCommandProvider.cs delete mode 100644 TUnit.Engine/Logging/TUnitVerbosity.cs diff --git a/TUnit.Engine/CommandLineProviders/VerbosityCommandProvider.cs b/TUnit.Engine/CommandLineProviders/VerbosityCommandProvider.cs deleted file mode 100644 index 097c7411330..00000000000 --- a/TUnit.Engine/CommandLineProviders/VerbosityCommandProvider.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Microsoft.Testing.Platform.CommandLine; -using Microsoft.Testing.Platform.Extensions; -using Microsoft.Testing.Platform.Extensions.CommandLine; -using TUnit.Engine.Logging; - -namespace TUnit.Engine.CommandLineProviders; - -internal class VerbosityCommandProvider(IExtension extension) : ICommandLineOptionsProvider -{ - public const string Verbosity = "verbosity"; - - public Task IsEnabledAsync() - { - return extension.IsEnabledAsync(); - } - - public string Uid => extension.Uid; - - public string Version => extension.Version; - - public string DisplayName => extension.DisplayName; - - public string Description => extension.Description; - - public IReadOnlyCollection GetCommandLineOptions() - { - return - [ - new CommandLineOption(Verbosity, "Output verbosity level: minimal, normal, verbose, debug (default: normal)", ArgumentArity.ExactlyOne, false) - ]; - } - - public Task ValidateOptionArgumentsAsync(CommandLineOption commandOption, string[] arguments) - { - if (commandOption.Name == Verbosity && arguments.Length != 1) - { - return ValidationResult.InvalidTask("A single verbosity level must be provided: minimal, normal, verbose, or debug"); - } - - if (commandOption.Name == Verbosity) - { - var verbosityArg = arguments[0].ToLowerInvariant(); - if (!IsValidVerbosity(verbosityArg)) - { - return ValidationResult.InvalidTask($"Invalid verbosity level '{arguments[0]}'. Valid options: minimal, normal, verbose, debug"); - } - } - - return ValidationResult.ValidTask; - } - - public Task ValidateCommandLineOptionsAsync(ICommandLineOptions commandLineOptions) - { - return ValidationResult.ValidTask; - } - - private static bool IsValidVerbosity(string verbosity) - { - return verbosity is "minimal" or "normal" or "verbose" or "debug"; - } - - /// - /// Parses verbosity from command line arguments - /// - public static TUnitVerbosity ParseVerbosity(string[] arguments) - { - if (arguments.Length == 0) - { - return TUnitVerbosity.Normal; - } - - return arguments[0].ToLowerInvariant() switch - { - "minimal" => TUnitVerbosity.Minimal, - "normal" => TUnitVerbosity.Normal, - "verbose" => TUnitVerbosity.Verbose, - "debug" => TUnitVerbosity.Debug, - _ => TUnitVerbosity.Normal - }; - } -} \ No newline at end of file diff --git a/TUnit.Engine/Extensions/TestApplicationBuilderExtensions.cs b/TUnit.Engine/Extensions/TestApplicationBuilderExtensions.cs index cd1e5691618..83b7f0c98ee 100644 --- a/TUnit.Engine/Extensions/TestApplicationBuilderExtensions.cs +++ b/TUnit.Engine/Extensions/TestApplicationBuilderExtensions.cs @@ -40,10 +40,7 @@ public static void AddTUnit(this ITestApplicationBuilder testApplicationBuilder) testApplicationBuilder.CommandLine.AddProvider(() => new ParallelismStrategyCommandProvider(extension)); testApplicationBuilder.CommandLine.AddProvider(() => new AdaptiveMetricsCommandProvider(extension)); - // Unified verbosity control (replaces HideTestOutput, DisableLogo) - testApplicationBuilder.CommandLine.AddProvider(() => new VerbosityCommandProvider(extension)); - - // Keep detailed stacktrace option for backward compatibility + // Keep detailed stacktrace option for backward compatibility testApplicationBuilder.CommandLine.AddProvider(() => new DetailedStacktraceCommandProvider(extension)); // GitHub reporter configuration diff --git a/TUnit.Engine/Framework/TUnitServiceProvider.cs b/TUnit.Engine/Framework/TUnitServiceProvider.cs index 6b19976aff9..a7cf8515259 100644 --- a/TUnit.Engine/Framework/TUnitServiceProvider.cs +++ b/TUnit.Engine/Framework/TUnitServiceProvider.cs @@ -75,7 +75,7 @@ public TUnitServiceProvider(IExtension extension, TestContext.Configuration = new ConfigurationAdapter(configuration); - VerbosityService = Register(new VerbosityService(CommandLineOptions)); + VerbosityService = Register(new VerbosityService(CommandLineOptions, frameworkServiceProvider)); DiscoveryDiagnostics.Initialize(VerbosityService); var logLevelProvider = Register(new LogLevelProvider(CommandLineOptions)); diff --git a/TUnit.Engine/Logging/TUnitVerbosity.cs b/TUnit.Engine/Logging/TUnitVerbosity.cs deleted file mode 100644 index 335ddf66cd6..00000000000 --- a/TUnit.Engine/Logging/TUnitVerbosity.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace TUnit.Engine.Logging; - -/// -/// Unified verbosity levels for TUnit output and diagnostics -/// -public enum TUnitVerbosity -{ - /// - /// Minimal output - errors and critical information only - /// - Minimal = 0, - - /// - /// Normal output - standard test results and basic information (default) - /// - Normal = 1, - - /// - /// Verbose output - detailed execution information and timing - /// - Verbose = 2, - - /// - /// Debug output - internal diagnostics, discovery details, and all framework information - /// - Debug = 3 -} - -/// -/// Extensions for working with TUnit verbosity levels -/// -public static class TUnitVerbosityExtensions -{ - /// - /// Checks if the current verbosity level includes the specified level - /// - public static bool Includes(this TUnitVerbosity current, TUnitVerbosity level) - { - return current >= level; - } - - /// - /// Converts verbosity to human-readable string - /// - public static string ToDisplayString(this TUnitVerbosity verbosity) - { - return verbosity switch - { - TUnitVerbosity.Minimal => "Minimal", - TUnitVerbosity.Normal => "Normal", - TUnitVerbosity.Verbose => "Verbose", - TUnitVerbosity.Debug => "Debug", - _ => verbosity.ToString() - }; - } -} \ No newline at end of file diff --git a/TUnit.Engine/Services/VerbosityService.cs b/TUnit.Engine/Services/VerbosityService.cs index 3e5e54fc94d..9339f1b88d1 100644 --- a/TUnit.Engine/Services/VerbosityService.cs +++ b/TUnit.Engine/Services/VerbosityService.cs @@ -1,98 +1,125 @@ using Microsoft.Testing.Platform.CommandLine; +using Microsoft.Testing.Platform.Services; using TUnit.Engine.CommandLineProviders; using TUnit.Engine.Helpers; -using TUnit.Engine.Logging; +using LogLevel = TUnit.Core.Logging.LogLevel; + +#pragma warning disable TPEXP namespace TUnit.Engine.Services; /// -/// Centralized service for managing TUnit output verbosity and diagnostic settings +/// Centralized service for managing TUnit output and diagnostic settings /// public sealed class VerbosityService { - private readonly TUnitVerbosity _verbosity; + private readonly bool _isDetailedOutput; + private readonly LogLevel _logLevel; - public VerbosityService(ICommandLineOptions commandLineOptions) + public VerbosityService(ICommandLineOptions commandLineOptions, IServiceProvider serviceProvider) { - _verbosity = GetVerbosityFromCommandLine(commandLineOptions); + _isDetailedOutput = GetOutputLevel(commandLineOptions, serviceProvider); + _logLevel = GetLogLevel(commandLineOptions); } /// - /// Current verbosity level + /// Whether to show detailed stack traces (enabled with Debug/Trace log level) /// - public TUnitVerbosity CurrentVerbosity => _verbosity; + public bool ShowDetailedStackTrace => _logLevel <= LogLevel.Debug; /// - /// Whether to show detailed stack traces (Verbose+ levels) + /// Whether to hide real-time test output (hidden with --output Normal) /// - public bool ShowDetailedStackTrace => _verbosity.Includes(TUnitVerbosity.Verbose); + public bool HideTestOutput => !_isDetailedOutput; /// - /// Whether to hide test output (Minimal level only) + /// Whether to show the TUnit logo /// - public bool HideTestOutput => _verbosity == TUnitVerbosity.Minimal; + public bool ShowLogo => true; /// - /// Whether to show the TUnit logo (Normal+ levels) + /// Whether to enable discovery diagnostics (enabled with Debug/Trace log level) /// - public bool ShowLogo => _verbosity.Includes(TUnitVerbosity.Normal); + public bool EnableDiscoveryDiagnostics => _logLevel <= LogLevel.Debug; /// - /// Whether to enable discovery diagnostics (Debug level only) + /// Whether to enable verbose source generator diagnostics (enabled with Debug/Trace log level) /// - public bool EnableDiscoveryDiagnostics => _verbosity.Includes(TUnitVerbosity.Debug); + public bool EnableVerboseSourceGeneratorDiagnostics => _logLevel <= LogLevel.Debug; /// - /// Whether to enable verbose source generator diagnostics (Debug level only) + /// Whether to show execution timing details (enabled with Debug/Trace log level) /// - public bool EnableVerboseSourceGeneratorDiagnostics => _verbosity.Includes(TUnitVerbosity.Debug); + public bool ShowExecutionTiming => _logLevel <= LogLevel.Debug; /// - /// Whether to show execution timing details (Verbose+ levels) + /// Whether to show parallel execution details (enabled with Debug/Trace log level) /// - public bool ShowExecutionTiming => _verbosity.Includes(TUnitVerbosity.Verbose); + public bool ShowParallelExecutionDetails => _logLevel <= LogLevel.Debug; /// - /// Whether to show parallel execution details (Debug level only) + /// Whether to show test discovery progress (enabled with Debug/Trace log level) /// - public bool ShowParallelExecutionDetails => _verbosity.Includes(TUnitVerbosity.Debug); + public bool ShowDiscoveryProgress => _logLevel <= LogLevel.Debug; /// - /// Whether to show test discovery progress (Verbose+ levels) + /// Whether to show memory and resource usage (enabled with Debug/Trace log level) /// - public bool ShowDiscoveryProgress => _verbosity.Includes(TUnitVerbosity.Verbose); + public bool ShowResourceUsage => _logLevel <= LogLevel.Debug; /// - /// Whether to show memory and resource usage (Debug level only) - /// - public bool ShowResourceUsage => _verbosity.Includes(TUnitVerbosity.Debug); - - /// - /// Creates a summary of current verbosity settings + /// Creates a summary of current output and diagnostic settings /// public string CreateVerbositySummary() { - return $"Verbosity: {_verbosity.ToDisplayString()} " + + var outputMode = _isDetailedOutput ? "Detailed" : "Normal"; + return $"Output: {outputMode}, Log Level: {_logLevel} " + $"(Stack traces: {ShowDetailedStackTrace}, " + - $"Logo: {ShowLogo}, " + $"Discovery diagnostics: {EnableDiscoveryDiagnostics})"; } // Use centralized environment variable cache - - private static TUnitVerbosity GetVerbosityFromCommandLine(ICommandLineOptions commandLineOptions) + + private static bool GetOutputLevel(ICommandLineOptions commandLineOptions, IServiceProvider serviceProvider) + { + // Check for --output flag (Microsoft.Testing.Platform extension) + if (commandLineOptions.TryGetOptionArgumentList("output", out var args) && args.Length > 0) + { + return args[0].Equals("Detailed", StringComparison.OrdinalIgnoreCase); + } + + // Smart defaults: Normal for console (buffered output), Detailed for IDE (real-time output) + return !IsConsoleEnvironment(serviceProvider); + } + + private static LogLevel GetLogLevel(ICommandLineOptions commandLineOptions) { - if (commandLineOptions.TryGetOptionArgumentList(VerbosityCommandProvider.Verbosity, out var args) && args.Length > 0) + // Check for --log-level flag + if (commandLineOptions.TryGetOptionArgumentList(LogLevelCommandProvider.LogLevelOption, out var args) && args.Length > 0) { - return VerbosityCommandProvider.ParseVerbosity(args); + return LogLevelCommandProvider.ParseLogLevel(args); } // Check cached legacy environment variable for backwards compatibility if (EnvironmentVariableCache.Get("TUNIT_DISCOVERY_DIAGNOSTICS") == "1") { - return TUnitVerbosity.Debug; + return LogLevel.Debug; } - return TUnitVerbosity.Normal; + return LogLevel.Information; + } + + private static bool IsConsoleEnvironment(IServiceProvider serviceProvider) + { + try + { + var clientInfo = serviceProvider.GetClientInfo(); + return clientInfo.Id.Contains("console", StringComparison.InvariantCultureIgnoreCase); + } + catch + { + // If we can't determine, default to console behavior + return true; + } } } \ No newline at end of file diff --git a/TUnit.Engine/TUnitMessageBus.cs b/TUnit.Engine/TUnitMessageBus.cs index b91c9875f3c..4a3c8743e94 100644 --- a/TUnit.Engine/TUnitMessageBus.cs +++ b/TUnit.Engine/TUnitMessageBus.cs @@ -9,6 +9,7 @@ using TUnit.Engine.CommandLineProviders; using TUnit.Engine.Exceptions; using TUnit.Engine.Extensions; +using TUnit.Engine.Logging; using TUnit.Engine.Services; #pragma warning disable TPEXP diff --git a/docs/docs/reference/command-line-flags.md b/docs/docs/reference/command-line-flags.md index a7a3dcca2c5..dd5c139fb43 100644 --- a/docs/docs/reference/command-line-flags.md +++ b/docs/docs/reference/command-line-flags.md @@ -44,9 +44,11 @@ Please note that for the coverage and trx report, you need to install [additiona List available tests. --log-level - Minimum log level for test output. - The available values are 'Trace', 'Debug', 'Information', 'Warning', 'Error', 'Critical', and 'None'. - Default is 'Information'. + Controls framework logging and diagnostic features. + The available values are: + - 'Trace' or 'Debug': Enable detailed stack traces, discovery diagnostics, timing details + - 'Information' (default): Normal framework behavior + - 'Warning', 'Error', 'Critical', or 'None': Minimal framework output --minimum-expected-tests Specifies the minimum number of tests that are expected to run. @@ -78,9 +80,6 @@ Please note that for the coverage and trx report, you need to install [additiona --fail-fast Cancel the test run after the first test failure - --hide-test-output - Hide Test Output - --maximum-parallel-tests Maximum Parallel Tests @@ -91,8 +90,12 @@ Please note that for the coverage and trx report, you need to install [additiona Disable reporting progress to screen. --output - Output verbosity when reporting tests. - Valid values are 'Normal', 'Detailed'. Default is 'Normal'. + Controls test result detail level AND real-time console output buffering. + - 'Normal': Show failures only + buffer test output (no real-time spam) + - 'Detailed': Show all tests + real-time test output + + Smart defaults: 'Normal' for console environments, 'Detailed' for IDE environments. + This prevents console spam while keeping IDEs responsive (each test has its own output window). --reflection Enable reflection mode for test discovery and execution (defaults to source generation mode)