Guide: Testing CLI Applications
The D20Tek.Spectre.Console.Extensions.Testing namespace provides context classes and an end-to-end runner that reduce the boilerplate of testing Spectre.Console CLIs. It captures console output and exit codes so you can assert on them.
Test a CommandAppBuilder-based app
CommandAppBuilderTestContext wraps a CommandAppBuilder and a TestConsole. Configure the builder as your app does, then run and assert:
var context = new CommandAppBuilderTestContext();
context.Builder
.WithDIContainer()
.WithStartup<Startup>()
.Build();
var result = await context.RunAsync(new[] { "greet", "World" });
Assert.AreEqual(0, result.ExitCode);
StringAssert.Contains(result.Output, "Hello, World");
Use Run/RunAsync for normal execution and RunWithException<T>/RunWithExceptionAsync<T> when you expect the app to throw a specific exception type.
Test with a type registrar directly
CommandAppTestContext sets up a registrar and a TestConsole without the builder. Configure commands through its Configure method:
var context = new CommandAppTestContext();
context.Configure(config => config.AddCommand<GreetCommand>("greet"));
var result = context.Run(new[] { "greet", "World" });
Assert.AreEqual(0, result.ExitCode);
Test command configuration
CommandConfigurationTestContext exposes a registrar, a resolver, and an ITestConfigurator so you can assert on how commands and branches are configured without running them.
End-to-end runs
CommandAppE2ERunner invokes a real Main entry point and captures its output as a CommandAppBasicResult:
var result = CommandAppE2ERunner.Run(Program.Main, "greet World");
Assert.AreEqual(0, result.ExitCode);
StringAssert.Contains(result.Output, "Hello, World");
Run has overloads that accept a command-line string or a pre-split string[].
Result types
CommandAppResult- exposes the exit code and captured console output for context-based runs.CommandAppBasicResult- exposesExitCodeandOutputfor end-to-end runs.