Skip to content

Commit e952153

Browse files
authored
Improve integration tests and code coverage report (#86)
Write the help of commands in alphabetic order
1 parent 9ebb5ea commit e952153

23 files changed

+118
-124
lines changed

azure-pipeline-build.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,21 @@ jobs:
2828
displayName: 'dotnet test'
2929
inputs:
3030
command: test
31-
projects: 'tests/**/*Tests.csproj'
32-
arguments: '-c $(System.Configuration) --no-build --logger "trx;LogFileName=TestsResults.trx" --logger "xunit;LogFileName=TestsResults.xml" /p:CollectCoverage=true /p:CoverletOutput=_BuildReports\Coverage\ /p:CoverletOutputFormat=cobertura /p:Exclude="[xunit.*]*%2c[*]JetBrains.*%2c[*Tests*]*"'
33-
continueOnError: true
31+
projects: 'tests/**Tests/*.csproj'
32+
arguments: '-c $(System.Configuration) --no-build /p:CollectCoverage=true /p:CoverletOutput=_BuildReports\Coverage\ /p:CoverletOutputFormat=cobertura /p:Exclude="[xunit.*]*%2c[*]JetBrains.*%2c[*Tests*]*"'
3433

3534
- task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@1
36-
displayName: ReportGenerator
35+
displayName: 'Generate code coverage report'
3736
inputs:
38-
reports: '**/_BuildReports/Coverage/coverage.cobertura.xml'
37+
reports: '**/*.IntegrationTests/_BuildReports/Coverage/coverage.cobertura.xml;**/*.UnitTests/_BuildReports/Coverage/coverage.cobertura.xml'
3938
targetdir: '$(Build.ArtifactStagingDirectory)/Coverage'
4039
condition: succeededOrFailed()
4140

4241
- task: PublishCodeCoverageResults@1
43-
displayName: 'Publish code coverage from **/_BuildReports/Coverage/coverage.cobertura.xml'
42+
displayName: 'Publish code coverage from $(Build.ArtifactStagingDirectory)/Coverage/Cobertura.xml'
4443
inputs:
4544
codeCoverageTool: Cobertura
46-
summaryFileLocation: '**/_BuildReports/Coverage/coverage.cobertura.xml'
45+
summaryFileLocation: '$(Build.ArtifactStagingDirectory)/Coverage/Cobertura.xml'
4746
reportDirectory: '$(Build.ArtifactStagingDirectory)/Coverage'
4847
condition: succeededOrFailed()
4948

src/MGR.CommandLineParser/Extensibility/DefaultHelpWriter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void WriteCommandListing()
4141
WriteGeneralInformation();
4242

4343
_console.WriteLine(Strings.DefaultHelpWriter_GlobalHelp_AvailableCommands);
44-
var commandTypes = _commandTypeProviders.GetAllVisibleCommandsTypes().ToList();
44+
var commandTypes = _commandTypeProviders.GetAllVisibleCommandsTypes().OrderBy(commandType => commandType.Metadata.Name).ToList();
4545
WriteDescriptionForSomeCommands(commandTypes);
4646
}
4747

@@ -81,7 +81,7 @@ public void WriteHelpForCommand(params ICommandType[] commandTypes)
8181

8282
WriteGeneralInformation();
8383
var parserOptions = _parserOptionsAccessor.Current;
84-
foreach (var commandType in commandTypes)
84+
foreach (var commandType in commandTypes.OrderBy(ct => ct.Metadata.Name))
8585
{
8686
var metadata = commandType.Metadata;
8787
_console.WriteLine(Strings.DefaultHelpWriter_CommandUsageFormat, parserOptions.CommandLineName, metadata.Name, metadata.Usage);

src/MGR.CommandLineParser/Extensions/TypeExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private static Type GetInterfaceType(this Type source, Type interfaceType)
9191
internal static bool IsType<T>(this Type source)
9292
{
9393
Guard.NotNull(source, nameof(source));
94-
return source.IsType(typeof (T));
94+
return source.IsType(typeof (T)) && source.IsClass;
9595
}
9696
internal static bool IsType(this Type source, Type baseType)
9797
{
Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,96 @@
11
using System;
2+
using System.Collections.Generic;
3+
using MGR.CommandLineParser.Command;
24
using MGR.CommandLineParser.Extensibility;
35
using MGR.CommandLineParser.UnitTests;
46
using Microsoft.Extensions.DependencyInjection;
7+
using Xunit;
58

69
namespace MGR.CommandLineParser.IntegrationTests
710
{
811
public abstract class ConsoleLoggingTestsBase
912
{
10-
protected static IServiceProvider CreateServiceProvider()
13+
private static readonly ServiceProvider _serviceProvider;
14+
#pragma warning disable S3963 // "static" fields should be initialized inline
15+
static ConsoleLoggingTestsBase()
1116
{
1217
var serviceCollection = new ServiceCollection();
1318
serviceCollection.AddScoped<IConsole, FakeConsole>();
1419
serviceCollection.AddCommandLineParser();
15-
return serviceCollection.BuildServiceProvider().CreateScope().ServiceProvider;
20+
_serviceProvider = serviceCollection.BuildServiceProvider();
21+
}
22+
#pragma warning restore S3963 // "static" fields should be initialized inline
23+
protected readonly FakeConsole _console;
24+
protected readonly IServiceProvider _scopedServiceProvider;
25+
protected ConsoleLoggingTestsBase()
26+
{
27+
_scopedServiceProvider = _serviceProvider.CreateScope().ServiceProvider;
28+
_console = (FakeConsole)_scopedServiceProvider.GetRequiredService<IConsole>();
29+
}
30+
31+
protected ParsingResult CallParse(IEnumerable<string> args)
32+
{
33+
var parserBuilder = new ParserBuilder();
34+
var parsingResult = CallParse(parserBuilder, args);
35+
36+
return parsingResult;
37+
}
38+
39+
protected ParsingResult CallParse(ParserBuilder parserBuilder, IEnumerable<string> args)
40+
{
41+
var parser = parserBuilder.BuildParser();
42+
var parsingResult = parser.Parse(args, _scopedServiceProvider);
43+
44+
return parsingResult;
45+
}
46+
protected ParsingResult CallParse<TCommand>(IEnumerable<string> args)
47+
where TCommand: class, ICommand
48+
{
49+
var parserBuilder = new ParserBuilder();
50+
var parsingResult = CallParse<TCommand>(parserBuilder, args);
51+
52+
return parsingResult;
53+
}
54+
55+
protected ParsingResult CallParse<TCommand>(ParserBuilder parserBuilder, IEnumerable<string> args)
56+
where TCommand : class, ICommand
57+
{
58+
var parser = parserBuilder.BuildParser();
59+
var parsingResult = parser.Parse<TCommand>(args, _scopedServiceProvider);
60+
61+
return parsingResult;
62+
}
63+
protected ParsingResult CallParseWithDefaultCommand<TCommand>(IEnumerable<string> args)
64+
where TCommand : class, ICommand
65+
{
66+
var parserBuilder = new ParserBuilder();
67+
var parsingResult = CallParseWithDefaultCommand<TCommand>(parserBuilder, args);
68+
69+
return parsingResult;
70+
}
71+
72+
protected ParsingResult CallParseWithDefaultCommand<TCommand>(ParserBuilder parserBuilder, IEnumerable<string> args)
73+
where TCommand : class, ICommand
74+
{
75+
var parser = parserBuilder.BuildParser();
76+
var parsingResult = parser.ParseWithDefaultCommand< TCommand>(args, _scopedServiceProvider);
77+
78+
return parsingResult;
79+
}
80+
81+
protected void AssertNoMessage()
82+
{
83+
var messages = _console.Messages;
84+
Assert.Empty(messages);
85+
}
86+
87+
protected void AssertOneMessageLoggedToConsole<TMessage>(string expectedMessage)
88+
where TMessage : FakeConsole.Message
89+
{
90+
var messages = _console.Messages;
91+
Assert.Single(messages);
92+
Assert.IsType<TMessage>(messages[0]);
93+
Assert.Equal(expectedMessage, messages[0].ToString(), ignoreLineEndingDifferences: true);
1694
}
1795
}
1896
}
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System.Collections.Generic;
2-
using MGR.CommandLineParser.Extensibility;
32
using MGR.CommandLineParser.UnitTests;
4-
using Microsoft.Extensions.DependencyInjection;
53
using Xunit;
64

75
namespace MGR.CommandLineParser.IntegrationTests.InvalidArguments
@@ -12,24 +10,16 @@ public class InexistingShortOptionTests : ConsoleLoggingTestsBase
1210
public void ParseWithInvalidArgs()
1311
{
1412
// Arrange
15-
var parserBuild = new ParserBuilder();
16-
var parser = parserBuild.BuildParser();
1713
IEnumerable<string> args = new[] { "delete", "--source:custom value", "-pn", "ApiKey", "MyApiKey", "Custom argument value", "b" };
1814
var expected = @"There is no option 'pn' for the command 'Delete'.
1915
";
20-
var serviceProvider = CreateServiceProvider();
21-
var console = (FakeConsole)serviceProvider.GetRequiredService<IConsole>();
22-
2316
// Act
24-
var parsingResult = parser.Parse(args, serviceProvider);
17+
var parsingResult = CallParse(args);
2518

2619
// Assert
2720
Assert.NotNull(parsingResult);
2821
Assert.Equal(CommandParsingResultCode.CommandParametersNotValid, parsingResult.ParsingResultCode);
29-
var messages = console.Messages;
30-
Assert.Single(messages);
31-
Assert.IsType<FakeConsole.ErrorMessage>(messages[0]);
32-
Assert.Equal(expected, messages[0].ToString(), ignoreLineEndingDifferences: true);
22+
AssertOneMessageLoggedToConsole<FakeConsole.ErrorMessage>(expected);
3323
}
3424
}
3525
}
Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System.Collections.Generic;
2-
using MGR.CommandLineParser.Extensibility;
32
using MGR.CommandLineParser.UnitTests;
4-
using Microsoft.Extensions.DependencyInjection;
53
using Xunit;
64

75
namespace MGR.CommandLineParser.IntegrationTests.InvalidArguments
@@ -12,24 +10,17 @@ public class InvalidShortNameFormatTests : ConsoleLoggingTestsBase
1210
public void ParseWithInvalidShortOption()
1311
{
1412
// Arrange
15-
var parserBuild = new ParserBuilder();
16-
var parser = parserBuild.BuildParser();
1713
IEnumerable<string> args = new[] { "import", "--p:50" };
1814
var expected = @"There is no option 'p' for the command 'Import'.
1915
";
20-
var serviceProvider = CreateServiceProvider();
21-
var console = (FakeConsole)serviceProvider.GetRequiredService<IConsole>();
2216

2317
// Act
24-
var parsingResult = parser.Parse(args, serviceProvider);
18+
var parsingResult = CallParse(args);
2519

2620
// Assert
2721
Assert.NotNull(parsingResult);
2822
Assert.Equal(CommandParsingResultCode.CommandParametersNotValid, parsingResult.ParsingResultCode);
29-
var messages = console.Messages;
30-
Assert.Single(messages);
31-
Assert.IsType<FakeConsole.ErrorMessage>(messages[0]);
32-
Assert.Equal(expected, messages[0].ToString(), ignoreLineEndingDifferences: true);
23+
AssertOneMessageLoggedToConsole<FakeConsole.ErrorMessage>(expected);
3324
}
3425
}
3526
}

tests/MGR.CommandLineParser.IntegrationTests/NotOkResultCode/CommandParameterNotValidTests.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,14 @@ public class CommandParameterNotValidTests : ConsoleLoggingTestsBase
1212
public void ParseWithCommandNameAndInvalidArgs()
1313
{
1414
// Arrange
15-
var parserBuild = new ParserBuilder();
16-
var parser = parserBuild.BuildParser();
1715
IEnumerable<string> args = new[] {"IntTest", "-i", "42", "Custom argument value", "-b"};
1816
var expectedReturnCode = CommandParsingResultCode.CommandParametersNotValid;
1917
var expectedNbOfArguments = 1;
2018
var expectedArgumentsValue = "Custom argument value";
2119
var expectedIntValue = 42;
2220

2321
// Act
24-
var actual = parser.Parse(args);
22+
var actual = CallParse(args);
2523

2624
// Assert
2725
Assert.False(actual.IsValid);
@@ -40,16 +38,14 @@ public void ParseWithCommandNameAndInvalidArgs()
4038
public void ParseWithSpecifiedCommandAndInvalidArgs()
4139
{
4240
// Arrange
43-
var parserBuild = new ParserBuilder();
44-
var parser = parserBuild.BuildParser();
4541
IEnumerable<string> args = new[] { "-i", "42", "Custom argument value", "-b" };
4642
var expectedReturnCode = CommandParsingResultCode.CommandParametersNotValid;
4743
var expectedNbOfArguments = 1;
4844
var expectedArgumentsValue = "Custom argument value";
4945
var expectedIntValue = 42;
5046

5147
// Act
52-
var actual = parser.Parse<IntTestCommand>(args);
48+
var actual = CallParse<IntTestCommand>(args);
5349

5450
// Assert
5551
Assert.False(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/NotOkResultCode/NoArgsTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ public class NoArgsTests : ConsoleLoggingTestsBase
88
public void ParseWithoutParameter()
99
{
1010
// Arrange
11-
var parserBuild = new ParserBuilder();
12-
var parser = parserBuild.BuildParser();
1311
var expectedReturnCode = CommandParsingResultCode.NoArgumentsProvided;
1412

1513
// Act
16-
var actual = parser.Parse(null);
14+
var actual = CallParse(null);
1715

1816
// Assert
1917
Assert.False(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/NotOkResultCode/NoCommandFoundTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ public class NoCommandFoundTests : ConsoleLoggingTestsBase
99
public void ParseWithBadCommandName()
1010
{
1111
// Arrange
12-
var parserBuild = new ParserBuilder();
13-
var parser = parserBuild.BuildParser();
1412
IEnumerable<string> args = new[] {"NotValid", "-option:true"};
1513
var expectedReturnCode = CommandParsingResultCode.NoCommandFound;
1614

1715
// Act
18-
var actual = parser.Parse(args);
16+
var actual = CallParse(args);
1917

2018
// Assert
2119
Assert.False(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/NotOkResultCode/NoCommandNameTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ public class NoCommandNameTests : ConsoleLoggingTestsBase
99
public void ParseWithEmptyParameter()
1010
{
1111
// Arrange
12-
var parserBuild = new ParserBuilder();
13-
var parser = parserBuild.BuildParser();
1412
IEnumerable<string> args = new List<string>();
1513
var expectedReturnCode = CommandParsingResultCode.NoCommandNameProvided;
1614

1715
// Act
18-
var actual = parser.Parse(args);
16+
var actual = CallParse(args);
1917

2018
// Assert
2119
Assert.False(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/SpecificCommand/CollectionOptionsTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ public class CollectionOptionsTests : ConsoleLoggingTestsBase
1212
public void ParseWithValidListArgs()
1313
{
1414
// Arrange
15-
var parserBuild = new ParserBuilder();
16-
var parser = parserBuild.BuildParser();
1715
IEnumerable<string> args = new[]
1816
{"--str-value:custom value", "-i", "42", "-il", "42", "Custom argument value", "-b"};
1917
var expectedReturnCode = CommandParsingResultCode.Success;
@@ -23,7 +21,7 @@ public void ParseWithValidListArgs()
2321
var expectedIntValue = 42;
2422

2523
// Act
26-
var actual = parser.Parse<IntTestCommand>(args);
24+
var actual = CallParse<IntTestCommand>(args);
2725

2826
// Assert
2927
Assert.True(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/SpecificCommand/EscapedTraillingArgumentTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ public class EscapedTraillingArgumentTests : ConsoleLoggingTestsBase
1111
public void ParseWithValidArgsAnDoubleDash()
1212
{
1313
// Arrange
14-
var parserBuild = new ParserBuilder();
15-
var parser = parserBuild.BuildParser();
1614
IEnumerable<string> args = new[] {"--str-value:custom value", "-i", "42", "Custom argument value", "-b", "--", "firstArg", "-i", "32"};
1715
var expectedReturnCode = CommandParsingResultCode.Success;
1816
var expectedStrValue = "custom value";
@@ -21,7 +19,7 @@ public void ParseWithValidArgsAnDoubleDash()
2119
var expectedIntValue = 42;
2220

2321
// Act
24-
var actual = parser.Parse<IntTestCommand>(args);
22+
var actual = CallParse<IntTestCommand>(args);
2523

2624
// Assert
2725
Assert.True(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/SpecificCommand/SimpleOptionsTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ public class SimpleOptionsTests : ConsoleLoggingTestsBase
1212
public void ParseWithValidArgs()
1313
{
1414
// Arrange
15-
var parserBuild = new ParserBuilder();
16-
var parser = parserBuild.BuildParser();
1715
IEnumerable<string> args = new[] {"--str-value:custom value", "-i", "42", "Custom argument value", "-b"};
1816
var expectedReturnCode = CommandParsingResultCode.Success;
1917
var expectedStrValue = "custom value";
@@ -22,7 +20,7 @@ public void ParseWithValidArgs()
2220
var expectedIntValue = 42;
2321

2422
// Act
25-
var actual = parser.Parse<IntTestCommand>(args);
23+
var actual = CallParse<IntTestCommand>(args);
2624

2725
// Assert
2826
Assert.True(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/UnspecifiedCommand/ArgumentsInResponseFileTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public class ArgumentsInResponseFileTests : ConsoleLoggingTestsBase
1111
public void ParseWithAResponseFile()
1212
{
1313
// Arrange
14-
var parser = new ParserBuilder().BuildParser();
1514
var tempFile = Path.GetRandomFileName();
1615
var tempResponseFileName = Path.ChangeExtension(tempFile, ".rsp");
1716
var tempFolder = Path.GetTempPath();
@@ -24,7 +23,7 @@ public void ParseWithAResponseFile()
2423
});
2524

2625
// Act
27-
var actual = parser.Parse(new[] { "@" + tempResponseFile });
26+
var actual = CallParse(new[] { "@" + tempResponseFile });
2827

2928
// Assert
3029
Assert.True(actual.IsValid);

tests/MGR.CommandLineParser.IntegrationTests/UnspecifiedCommand/CollectionArgumentTests.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)