Refactor tests and make them more consistent

This commit is contained in:
Alexey Golub
2019-08-20 12:40:56 +03:00
parent 256b693466
commit 272c079767
10 changed files with 223 additions and 134 deletions

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Exceptions;
using CliFx.Services;
@@ -8,21 +9,45 @@ namespace CliFx.Tests
public partial class CliApplicationTests
{
[Command]
private class TestDefaultCommand : ICommand
private class DefaultCommand : ICommand
{
public Task ExecuteAsync(IConsole console) => Task.CompletedTask;
public Task ExecuteAsync(IConsole console)
{
console.Output.WriteLine("DefaultCommand executed.");
return Task.CompletedTask;
}
}
[Command("command")]
private class TestNamedCommand : ICommand
[Command("cmd")]
private class NamedCommand : ICommand
{
public Task ExecuteAsync(IConsole console) => Task.CompletedTask;
public Task ExecuteAsync(IConsole console)
{
console.Output.WriteLine("NamedCommand executed.");
return Task.CompletedTask;
}
}
}
// Negative
public partial class CliApplicationTests
{
[Command("faulty1")]
private class FaultyCommand1 : ICommand
{
public Task ExecuteAsync(IConsole console) => throw new CommandException(150);
}
[Command("faulty command")]
private class TestFaultyCommand : ICommand
[Command("faulty2")]
private class FaultyCommand2 : ICommand
{
public Task ExecuteAsync(IConsole console) => Task.FromException(new CommandException(-1337));
public Task ExecuteAsync(IConsole console) => throw new CommandException("FaultyCommand2 error message.", 150);
}
[Command("faulty3")]
private class FaultyCommand3 : ICommand
{
public Task ExecuteAsync(IConsole console) => throw new Exception("FaultyCommand3 error message.");
}
}
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using CliFx.Services;
using FluentAssertions;
using NUnit.Framework;
@@ -11,151 +13,139 @@ namespace CliFx.Tests
{
private static IEnumerable<TestCaseData> GetTestCases_RunAsync()
{
// Specified command is defined
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"command"}
new[] {typeof(DefaultCommand)},
new string[0],
"DefaultCommand executed."
);
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"command", "--help"}
new[] {typeof(NamedCommand)},
new[] {"cmd"},
"NamedCommand executed."
);
}
private static IEnumerable<TestCaseData> GetTestCases_HelpAndVersion_RunAsync()
{
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"command", "-h"}
);
// Default command is defined
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {typeof(DefaultCommand)},
new string[0]
);
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {"--version"}
new[] {typeof(DefaultCommand)},
new[] {"-h"}
);
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {typeof(DefaultCommand)},
new[] {"--help"}
);
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {"-h"}
new[] {typeof(DefaultCommand)},
new[] {"--version"}
);
// Default command is not defined
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {typeof(NamedCommand)},
new string[0]
);
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"--version"}
new[] {typeof(NamedCommand)},
new[] {"cmd", "-h"}
);
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"--help"}
new[] {typeof(FaultyCommand1)},
new[] {"faulty1", "-h"}
);
yield return new TestCaseData(
new[] {typeof(TestNamedCommand)},
new[] {"-h"}
);
// Specified a faulty command
yield return new TestCaseData(
new[] {typeof(TestFaultyCommand)},
new[] {"faulty", "command", "--help"}
new[] {typeof(FaultyCommand2)},
new[] {"faulty2", "-h"}
);
yield return new TestCaseData(
new[] {typeof(TestFaultyCommand)},
new[] {"faulty", "command", "-h"}
new[] {typeof(FaultyCommand3)},
new[] {"faulty3", "-h"}
);
}
private static IEnumerable<TestCaseData> GetTestCases_RunAsync_Negative()
{
// No commands defined
yield return new TestCaseData(
new Type[0],
new string[0]
);
yield return new TestCaseData(
new Type[0],
new[] {"--version"}
new[] {typeof(DefaultCommand)},
new[] {"non-existing"}
);
yield return new TestCaseData(
new Type[0],
new[] {"--help"}
new[] {typeof(FaultyCommand1)},
new[] {"faulty1"}
);
yield return new TestCaseData(
new Type[0],
new[] {"-h"}
new[] {typeof(FaultyCommand2)},
new[] {"faulty2"}
);
yield return new TestCaseData(
new Type[0],
new[] {"command"}
);
yield return new TestCaseData(
new Type[0],
new[] {"faulty", "command"}
);
// Specified command is not defined
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {"command"}
);
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {"command", "--help"}
);
yield return new TestCaseData(
new[] {typeof(TestDefaultCommand)},
new[] {"command", "-h"}
);
// Specified a faulty command
yield return new TestCaseData(
new[] {typeof(TestFaultyCommand)},
new[] {"faulty", "command"}
new[] {typeof(FaultyCommand3)},
new[] {"faulty3"}
);
}
[Test]
[TestCaseSource(nameof(GetTestCases_RunAsync))]
public async Task RunAsync_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments)
public async Task RunAsync_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments, string expectedStdOut)
{
// Arrange
var application = new CliApplicationBuilder().AddCommands(commandTypes).Build();
using (var stdout = new StringWriter())
{
var console = new VirtualConsole(stdout);
// Act
var exitCodeValue = await application.RunAsync(commandLineArguments);
var application = new CliApplicationBuilder()
.AddCommands(commandTypes)
.UseConsole(console)
.Build();
// Assert
exitCodeValue.Should().Be(0);
// Act
var exitCode = await application.RunAsync(commandLineArguments);
// Assert
exitCode.Should().Be(0);
stdout.ToString().Trim().Should().Be(expectedStdOut);
}
}
[Test]
[TestCaseSource(nameof(GetTestCases_HelpAndVersion_RunAsync))]
public async Task RunAsync_HelpAndVersion_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments)
{
// Arrange
using (var stdout = new StringWriter())
{
var console = new VirtualConsole(stdout);
var application = new CliApplicationBuilder()
.AddCommands(commandTypes)
.UseConsole(console)
.Build();
// Act
var exitCode = await application.RunAsync(commandLineArguments);
// Assert
exitCode.Should().Be(0);
stdout.ToString().Should().NotBeNullOrWhiteSpace();
}
}
[Test]
@@ -163,13 +153,22 @@ namespace CliFx.Tests
public async Task RunAsync_Negative_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments)
{
// Arrange
var application = new CliApplicationBuilder().AddCommands(commandTypes).Build();
using (var stderr = new StringWriter())
{
var console = new VirtualConsole(TextWriter.Null, stderr);
// Act
var exitCodeValue = await application.RunAsync(commandLineArguments);
var application = new CliApplicationBuilder()
.AddCommands(commandTypes)
.UseConsole(console)
.Build();
// Assert
exitCodeValue.Should().NotBe(0);
// Act
var exitCode = await application.RunAsync(commandLineArguments);
// Assert
exitCode.Should().NotBe(0);
stderr.ToString().Should().NotBeNullOrWhiteSpace();
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CliFx.Models;
using CliFx.Services;
using FluentAssertions;
@@ -10,23 +11,26 @@ namespace CliFx.Tests
[TestFixture]
public partial class CommandFactoryTests
{
private static CommandSchema GetCommandSchema(Type commandType) =>
new CommandSchemaResolver().GetCommandSchemas(new[] {commandType}).Single();
private static IEnumerable<TestCaseData> GetTestCases_CreateCommand()
{
yield return new TestCaseData(typeof(TestCommand));
yield return new TestCaseData(GetCommandSchema(typeof(TestCommand)));
}
[Test]
[TestCaseSource(nameof(GetTestCases_CreateCommand))]
public void CreateCommand_Test(Type commandType)
public void CreateCommand_Test(CommandSchema commandSchema)
{
// Arrange
var factory = new CommandFactory();
// Act
var command = factory.CreateCommand(new CommandSchema(commandType, null, null, new CommandOptionSchema[0]));
var command = factory.CreateCommand(commandSchema);
// Assert
command.Should().BeOfType(commandType);
command.Should().BeOfType(commandSchema.Type);
}
}
}

View File

@@ -1,8 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using CliFx.Exceptions;
using CliFx.Models;
using CliFx.Services;
using CliFx.Tests.Internal;
using FluentAssertions;
using NUnit.Framework;
@@ -11,9 +12,14 @@ namespace CliFx.Tests
[TestFixture]
public partial class CommandInitializerTests
{
private static CommandSchema GetCommandSchema(Type commandType) =>
new CommandSchemaResolver().GetCommandSchemas(new[] {commandType}).Single();
private static IEnumerable<TestCaseData> GetTestCases_InitializeCommand()
{
yield return new TestCaseData(
new TestCommand(),
GetCommandSchema(typeof(TestCommand)),
new CommandInput(new[]
{
new CommandOptionInput("int", "13")
@@ -22,6 +28,8 @@ namespace CliFx.Tests
);
yield return new TestCaseData(
new TestCommand(),
GetCommandSchema(typeof(TestCommand)),
new CommandInput(new[]
{
new CommandOptionInput("int", "13"),
@@ -31,6 +39,8 @@ namespace CliFx.Tests
);
yield return new TestCaseData(
new TestCommand(),
GetCommandSchema(typeof(TestCommand)),
new CommandInput(new[]
{
new CommandOptionInput("i", "13")
@@ -39,11 +49,17 @@ namespace CliFx.Tests
);
}
private static IEnumerable<TestCaseData> GetTestCases_InitializeCommand_IsRequired()
private static IEnumerable<TestCaseData> GetTestCases_InitializeCommand_Negative()
{
yield return new TestCaseData(CommandInput.Empty);
yield return new TestCaseData(
new TestCommand(),
GetCommandSchema(typeof(TestCommand)),
CommandInput.Empty
);
yield return new TestCaseData(
new TestCommand(),
GetCommandSchema(typeof(TestCommand)),
new CommandInput(new[]
{
new CommandOptionInput("str", "hello world")
@@ -53,31 +69,27 @@ namespace CliFx.Tests
[Test]
[TestCaseSource(nameof(GetTestCases_InitializeCommand))]
public void InitializeCommand_Test(CommandInput commandInput, ICommand expectedCommand)
public void InitializeCommand_Test(ICommand command, CommandSchema commandSchema, CommandInput commandInput, ICommand expectedCommand)
{
// Arrange
var initializer = new CommandInitializer();
var schema = new CommandSchemaResolver().GetCommandSchema(typeof(TestCommand));
var command = new TestCommand();
// Act
initializer.InitializeCommand(command, schema, commandInput);
initializer.InitializeCommand(command, commandSchema, commandInput);
// Assert
command.Should().BeEquivalentTo(expectedCommand, o => o.RespectingRuntimeTypes());
}
[Test]
[TestCaseSource(nameof(GetTestCases_InitializeCommand_IsRequired))]
public void InitializeCommand_IsRequired_Test(CommandInput commandInput)
[TestCaseSource(nameof(GetTestCases_InitializeCommand_Negative))]
public void InitializeCommand_Negative_Test(ICommand command, CommandSchema commandSchema, CommandInput commandInput)
{
// Arrange
var initializer = new CommandInitializer();
var schema = new CommandSchemaResolver().GetCommandSchema(typeof(TestCommand));
var command = new TestCommand();
// Act & Assert
initializer.Invoking(i => i.InitializeCommand(command, schema, commandInput))
initializer.Invoking(i => i.InitializeCommand(command, commandSchema, commandInput))
.Should().ThrowExactly<MissingCommandOptionInputException>();
}
}

View File

@@ -157,6 +157,14 @@ namespace CliFx.Tests
new[] {"long", "command", "name"},
new CommandInput("long command name")
);
yield return new TestCaseData(
new[] {"long", "command", "name", "--option", "value"},
new CommandInput("long command name", new[]
{
new CommandOptionInput("option", "value")
})
);
}
[Test]

View File

@@ -280,10 +280,10 @@ namespace CliFx.Tests
public void ConvertOptionInput_Test(CommandOptionInput optionInput, Type targetType, object expectedConvertedValue)
{
// Arrange
var commandOptionInputConverter = new CommandOptionInputConverter();
var converter = new CommandOptionInputConverter();
// Act
var convertedValue = commandOptionInputConverter.ConvertOptionInput(optionInput, targetType);
var convertedValue = converter.ConvertOptionInput(optionInput, targetType);
// Assert
convertedValue.Should().BeEquivalentTo(expectedConvertedValue);
@@ -295,11 +295,11 @@ namespace CliFx.Tests
public void ConvertOptionInput_Negative_Test(CommandOptionInput optionInput, Type targetType)
{
// Arrange
var commandOptionInputConverter = new CommandOptionInputConverter();
var converter = new CommandOptionInputConverter();
// Act & Assert
commandOptionInputConverter.Invoking(c => c.ConvertOptionInput(optionInput, targetType)).Should()
.ThrowExactly<InvalidCommandOptionInputException>();
converter.Invoking(c => c.ConvertOptionInput(optionInput, targetType))
.Should().ThrowExactly<InvalidCommandOptionInputException>();
}
}
}

View File

@@ -84,11 +84,11 @@ namespace CliFx.Tests
public void GetCommandSchemas_Negative_Test(IReadOnlyList<Type> commandTypes)
{
// Arrange
var commandSchemaResolver = new CommandSchemaResolver();
var resolver = new CommandSchemaResolver();
// Act & Assert
commandSchemaResolver.Invoking(r => r.GetCommandSchemas(commandTypes)).Should()
.ThrowExactly<InvalidCommandSchemaException>();
resolver.Invoking(r => r.GetCommandSchemas(commandTypes))
.Should().ThrowExactly<InvalidCommandSchemaException>();
}
}
}

View File

@@ -0,0 +1,15 @@
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Services;
namespace CliFx.Tests
{
public partial class DelegateCommandFactoryTests
{
[Command]
private class TestCommand : ICommand
{
public Task ExecuteAsync(IConsole console) => Task.CompletedTask;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CliFx.Models;
using CliFx.Services;
using FluentAssertions;
using NUnit.Framework;
namespace CliFx.Tests
{
[TestFixture]
public partial class DelegateCommandFactoryTests
{
private static CommandSchema GetCommandSchema(Type commandType) =>
new CommandSchemaResolver().GetCommandSchemas(new[] {commandType}).Single();
private static IEnumerable<TestCaseData> GetTestCases_CreateCommand()
{
yield return new TestCaseData(
new Func<CommandSchema, ICommand>(schema => (ICommand) Activator.CreateInstance(schema.Type)),
GetCommandSchema(typeof(TestCommand))
);
}
[Test]
[TestCaseSource(nameof(GetTestCases_CreateCommand))]
public void CreateCommand_Test(Func<CommandSchema, ICommand> factoryMethod, CommandSchema commandSchema)
{
// Arrange
var factory = new DelegateCommandFactory(factoryMethod);
// Act
var command = factory.CreateCommand(commandSchema);
// Assert
command.Should().BeOfType(commandSchema.Type);
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Linq;
using CliFx.Models;
using CliFx.Services;
namespace CliFx.Tests.Internal
{
internal static class Extensions
{
public static CommandSchema GetCommandSchema(this ICommandSchemaResolver resolver, Type commandType) =>
resolver.GetCommandSchemas(new[] {commandType}).Single();
}
}