Improve tests

This commit is contained in:
Tyrrrz
2020-10-23 21:18:57 +03:00
parent b120138de3
commit 14ad9d5738
6 changed files with 100 additions and 22 deletions

View File

@@ -275,11 +275,8 @@ namespace CliFx.Analyzers
private static void CheckCommandType(SymbolAnalysisContext context) private static void CheckCommandType(SymbolAnalysisContext context)
{ {
// Named type: MyCommand // Named type: MyCommand
if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol)) if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol) ||
return; namedTypeSymbol.TypeKind != TypeKind.Class)
// Only classes
if (namedTypeSymbol.TypeKind != TypeKind.Class)
return; return;
// Implements ICommand? // Implements ICommand?

View File

@@ -913,7 +913,7 @@ namespace CliFx.Tests
} }
[Fact] [Fact]
public async Task Argument_value_can_be_bound_to_an_enum_type_by_name() public async Task Argument_value_can_be_bound_to_enum_type_by_name()
{ {
// Arrange // Arrange
var (console, stdOut, _) = VirtualConsole.CreateBuffered(); var (console, stdOut, _) = VirtualConsole.CreateBuffered();
@@ -941,7 +941,7 @@ namespace CliFx.Tests
} }
[Fact] [Fact]
public async Task Argument_value_can_be_bound_to_an_enum_type_by_id() public async Task Argument_value_can_be_bound_to_enum_type_by_id()
{ {
// Arrange // Arrange
var (console, stdOut, _) = VirtualConsole.CreateBuffered(); var (console, stdOut, _) = VirtualConsole.CreateBuffered();
@@ -1318,6 +1318,54 @@ namespace CliFx.Tests
}); });
} }
[Fact]
public async Task Argument_value_can_only_be_bound_if_the_target_type_is_supported()
{
// Arrange
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<UnsupportedArgumentTypesCommand>()
.UseConsole(console)
.Build();
// Act
var exitCode = await application.RunAsync(new[]
{
"cmd", "--custom"
});
// Assert
exitCode.Should().NotBe(0);
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Argument_value_can_only_be_bound_if_the_provided_value_can_be_converted_to_the_target_type()
{
// Arrange
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
.UseConsole(console)
.Build();
// Act
var exitCode = await application.RunAsync(new[]
{
"cmd", "--int", "foo"
});
// Assert
exitCode.Should().NotBe(0);
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErr.GetString());
}
[Fact] [Fact]
public async Task Argument_value_can_only_be_bound_to_non_nullable_type_if_it_is_set() public async Task Argument_value_can_only_be_bound_to_non_nullable_type_if_it_is_set()
{ {
@@ -1365,5 +1413,29 @@ namespace CliFx.Tests
_output.WriteLine(stdErr.GetString()); _output.WriteLine(stdErr.GetString());
} }
[Fact]
public async Task Argument_values_can_only_be_bound_to_a_type_that_implements_IEnumerable_and_can_be_converted_from_an_array()
{
// Arrange
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<UnsupportedArgumentTypesCommand>()
.UseConsole(console)
.Build();
// Act
var exitCode = await application.RunAsync(new[]
{
"cmd", "--custom-enumerable"
});
// Assert
exitCode.Should().NotBe(0);
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErr.GetString());
}
} }
} }

View File

@@ -8,11 +8,11 @@ namespace CliFx.Tests.Commands
[Command("cmd")] [Command("cmd")]
public partial class UnsupportedArgumentTypesCommand : SelfSerializeCommandBase public partial class UnsupportedArgumentTypesCommand : SelfSerializeCommandBase
{ {
[CommandOption("str-non-initializable")] [CommandOption("custom")]
public CustomType? StringNonInitializable { get; set; } public CustomType? CustomNonConvertible { get; set; }
[CommandOption("str-enumerable-non-initializable")] [CommandOption("custom-enumerable")]
public CustomEnumerable<string>? StringEnumerableNonInitializable { get; set; } public CustomEnumerable<string>? CustomEnumerableNonConvertible { get; set; }
} }
public partial class UnsupportedArgumentTypesCommand public partial class UnsupportedArgumentTypesCommand

View File

@@ -165,9 +165,9 @@ namespace CliFx
/// </summary> /// </summary>
public CliApplication Build() public CliApplication Build()
{ {
_title ??= TryGetDefaultTitle() ?? "App"; _title ??= GetDefaultTitle();
_executableName ??= TryGetDefaultExecutableName() ?? "app"; _executableName ??= GetDefaultExecutableName();
_versionText ??= TryGetDefaultVersionText() ?? "v1.0"; _versionText ??= GetDefaultVersionText();
_console ??= new SystemConsole(); _console ??= new SystemConsole();
_typeActivator ??= new DefaultTypeActivator(); _typeActivator ??= new DefaultTypeActivator();
@@ -185,23 +185,29 @@ namespace CliFx
// Entry assembly is null in tests // Entry assembly is null in tests
private static Assembly? EntryAssembly => LazyEntryAssembly.Value; private static Assembly? EntryAssembly => LazyEntryAssembly.Value;
private static string? TryGetDefaultTitle() => EntryAssembly?.GetName().Name; private static string GetDefaultTitle() => EntryAssembly?.GetName().Name?? "App";
private static string? TryGetDefaultExecutableName() private static string GetDefaultExecutableName()
{ {
var entryAssemblyLocation = EntryAssembly?.Location; var entryAssemblyLocation = EntryAssembly?.Location;
// The assembly can be an executable or a dll, depending on how it was packaged // The assembly can be an executable or a dll, depending on how it was packaged
var isDll = string.Equals(Path.GetExtension(entryAssemblyLocation), ".dll", StringComparison.OrdinalIgnoreCase); var isDll = string.Equals(
Path.GetExtension(entryAssemblyLocation),
".dll",
StringComparison.OrdinalIgnoreCase
);
return isDll var name = isDll
? "dotnet " + Path.GetFileName(entryAssemblyLocation) ? "dotnet " + Path.GetFileName(entryAssemblyLocation)
: Path.GetFileNameWithoutExtension(entryAssemblyLocation); : Path.GetFileNameWithoutExtension(entryAssemblyLocation);
return name ?? "app";
} }
private static string? TryGetDefaultVersionText() => private static string GetDefaultVersionText() =>
EntryAssembly != null EntryAssembly != null
? $"v{EntryAssembly.GetName().Version.ToSemanticString()}" ? $"v{EntryAssembly.GetName().Version.ToSemanticString()}"
: null; : "v1.0";
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using CliFx.Exceptions; using CliFx.Exceptions;
using CliFx.Internal.Extensions;
namespace CliFx namespace CliFx
{ {
@@ -13,7 +14,7 @@ namespace CliFx
{ {
try try
{ {
return Activator.CreateInstance(type); return type.CreateInstance();
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -8,7 +8,9 @@ namespace CliFx.Internal.Extensions
{ {
internal static class TypeExtensions internal static class TypeExtensions
{ {
public static T CreateInstance<T>(this Type type) => (T) Activator.CreateInstance(type); public static object CreateInstance(this Type type) => Activator.CreateInstance(type);
public static T CreateInstance<T>(this Type type) => (T) type.CreateInstance();
public static bool Implements(this Type type, Type interfaceType) => type.GetInterfaces().Contains(interfaceType); public static bool Implements(this Type type, Type interfaceType) => type.GetInterfaces().Contains(interfaceType);