Testing Command-Line Applications

How to test CLI apps built with Spectre.Console.Cli to ensure they parse and execute correctly

To test CLI applications, use CommandAppTester from Spectre.Console.Cli.Testing. It runs commands in-memory and captures exit codes and output for assertions.

Make Commands Testable

Inject IAnsiConsole instead of using the static AnsiConsole directly. This allows tests to capture output:

public class GreetCommand : Command<GreetCommand.Settings>
{
    private readonly IAnsiConsole _console;
  
    public class Settings : CommandSettings
    {
        [CommandArgument(0, "<name>")]
        [Description("Name to greet")]
        public string Name { get; init; } = string.Empty;
  
        [CommandOption("-c|--count")]
        [Description("Number of times to greet")]
        [DefaultValue(1)]
        public int Count { get; init; } = 1;
    }
  
    public GreetCommand(IAnsiConsole console)
    {
        _console = console;
    }
  
    protected override int Execute(CommandContext context, Settings settings, CancellationToken cancellation)
    {
        for (var i = 0; i < settings.Count; i++)
        {
            _console.MarkupLine($"Hello, [green]{settings.Name}[/]!");
        }
        return 0;
    }
}

Test with CommandAppTester

Install the testing package:

dotnet add package Spectre.Console.Cli.Testing

Configure the tester like a regular CommandApp, then call Run with arguments. The result provides ExitCode, Output, and Settings for assertions:

[Fact]
public void Greet_WithName_ReturnsZeroAndOutputsGreeting()
{
    // Arrange
    var app = new CommandAppTester();
    app.SetDefaultCommand<GreetCommand>();
  
    // Act
    var result = app.Run("World");
  
    // Assert
    Assert.Equal(0, result.ExitCode);
    Assert.Contains("Hello", result.Output);
    Assert.Contains("World", result.Output);
}

You can also verify that command-line arguments were parsed correctly:

[Fact]
public void Greet_WithCount_ParsesSettingsCorrectly()
{
    // Arrange
    var app = new CommandAppTester();
    app.SetDefaultCommand<GreetCommand>();
  
    // Act
    var result = app.Run("Alice", "--count", "3");
  
    // Assert
    Assert.Equal(0, result.ExitCode);
  
    // Verify settings were parsed correctly
    var settings = result.Settings as GreetCommand.Settings;
    Assert.NotNull(settings);
    Assert.Equal("Alice", settings!.Name);
    Assert.Equal(3, settings.Count);
}

Test Interactive Prompts

For commands with prompts, use TestConsole to queue input before running:

[Fact]
public void Interactive_WithQueuedInput_ProcessesCorrectly()
{
    // Arrange - queue up user input before running
    var console = new TestConsole();
    console.Profile.Capabilities.Interactive = true;
    console.Input.PushTextWithEnter("yes");
  
    var app = new CommandAppTester(console: console);
    app.SetDefaultCommand<ConfirmCommand>();
  
    // Act
    var result = app.Run();
  
    // Assert
    Assert.Equal(0, result.ExitCode);
    Assert.Contains("Confirmed", result.Output);
}

Use PushKey for arrow keys and enter, PushTextWithEnter for text input.

See Also