command-line-api icon indicating copy to clipboard operation
command-line-api copied to clipboard

Dry run mode so that tests can verify that the entry point hasn't been broken

Open jnm2 opened this issue 2 years ago • 2 comments

Updating from beta1.20574.7 to beta2.21617.1 caused the app to stop working because I hadn't seen https://github.com/dotnet/command-line-api/issues/1537:

Unhandled exception: System.ArgumentException: Service not found for type System.Uri.

I'd like to be able to write a unit test that passes a set of arguments to the app entry point and verifies that no such issue is incurred, but without actually invoking the handler. I thought of a [dryrun] directive. Maybe even cooler would be if this was possible in the test code:

object?[] handlerArguments = Handler.Verify(() => Program.Main(new[] { "arg1", "arg2" }));
// Assert that the arguments are as expected

jnm2 avatar Mar 12 '22 01:03 jnm2

Using a DIY interceptor (defined at https://gist.github.com/jnm2/33bf88669982fce23cd2a00945884670):

// In Program.Main
command.Handler = CommandHandler.Create(CommandVerifier.Intercept(MigrateAsync));
using NUnit.Framework;
using Shouldly;

public static class EntryPointTests
{
    [Test]
    public static async Task No_System_CommandLine_failure_for_minimal_arguments()
    {
        var arguments = await CommandVerifier.VerifyArgumentsAsync(async () =>
            await Program.Main(new[] { "http://someurl", "$/SomePath", "--authors", "authors.txt" }));

        arguments[0].ShouldBe(new Uri("http://someurl"));
        arguments[1].ShouldBe("$/SomePath");
        arguments[2].ShouldBe("authors.txt");
        // Maybe Dictionary<string, object?> would have been better than object?[]
    }
}

It would be great if something like this was built in.

jnm2 avatar Mar 12 '22 03:03 jnm2

You can do some of this by exposing the configured Parser to your tests and then parsing various command lines and verifying their results directly. Example: https://github.com/dotnet/interactive/blob/97a0651d15d6506bfe0a15dd5e74f8a29568eca4/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs#L198-L208

And if you need to verify even more of the pipeline from within you handler, you can structure your code to allow a dummy delegate to be passed by your tests. Example: https://github.com/dotnet/interactive/blob/97a0651d15d6506bfe0a15dd5e74f8a29568eca4/src/dotnet-interactive.Tests/CommandLine/CommandLineParserTests.cs#L50-L76

jonsequitur avatar Apr 22 '22 21:04 jonsequitur