Skip to content

Commit

Permalink
Merge pull request #384 from tonyhallett/fix-excludebyattribute-cover…
Browse files Browse the repository at this point in the history
…let-unqualified-only

Fix excludebyattribute coverlet unqualified only
  • Loading branch information
tonyhallett committed Jan 18, 2024
2 parents 6494314 + 3412781 commit a5af270
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 152 deletions.
181 changes: 166 additions & 15 deletions FineCodeCoverageTests/CoverletConsole_Tests.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AutoMoq;
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine.Coverlet;
using FineCodeCoverage.Engine.Model;
using FineCodeCoverage.Engine.OpenCover;
using FineCodeCoverage.Options;
using Moq;
using NUnit.Framework;

namespace Test
{
public class CoverletConsoleUtil_Tests

public class CoverletExeArgumentsProvider_Tests
{
private AutoMoqer mocker;
private CoverletConsoleUtil coverletConsoleUtil;
[Test]
public void Should_Have_ExcludeByAttribute_Setting_For_Each_ExcludeByAttribute()
{
var mockCoverageProject = SafeMockCoverageProject();
mockCoverageProject.SetupGet(cp => cp.Settings.ExcludeByAttribute).Returns(new[] { "ExcludeByAttribute1", "ExcludeByAttribute2" });

[SetUp]
public void SetUp()
var coverletExeArgumentsProvider = new CoverletExeArgumentsProvider();
var coverletSettings = coverletExeArgumentsProvider.GetArguments(mockCoverageProject.Object);

AssertHasSetting(coverletSettings, "--exclude-by-attribute ExcludeByAttribute1");
AssertHasSetting(coverletSettings, "--exclude-by-attribute ExcludeByAttribute2");
}

[Test] //https://github.com/coverlet-coverage/coverlet/issues/1589
public void Should_Unqualified_Qualified_ExcludeByAttribute()
{
mocker = new AutoMoqer();
coverletConsoleUtil = mocker.Create<CoverletConsoleUtil>();
var mockCoverageProject = SafeMockCoverageProject();
mockCoverageProject.SetupGet(cp => cp.Settings.ExcludeByAttribute).Returns(new[] { "Namespace.ExcludeByAttribute1"});

var coverletExeArgumentsProvider = new CoverletExeArgumentsProvider();
var coverletSettings = coverletExeArgumentsProvider.GetArguments(mockCoverageProject.Object);

AssertHasSetting(coverletSettings, "--exclude-by-attribute ExcludeByAttribute1");
}
[Test]
public void Should_Initilize_IFCCCoverletConsoleExeProvider()

private Mock<ICoverageProject> SafeMockCoverageProject()
{
var ct = CancellationToken.None;
coverletConsoleUtil.Initialize("appDataFolder", ct);
mocker.Verify<IFCCCoverletConsoleExecutor>(fccExeProvider => fccExeProvider.Initialize("appDataFolder", ct));
var mockCoverageProject = new Mock<ICoverageProject>();
mockCoverageProject.SetupGet(coverageProject => coverageProject.IncludedReferencedProjects).Returns(new List<string>());
mockCoverageProject.SetupGet(coverageProject => coverageProject.ExcludedReferencedProjects).Returns(new List<string>());
mockCoverageProject.SetupGet(coverageProject => coverageProject.Settings).Returns(new Mock<IAppOptions>().Object);
return mockCoverageProject;
}

private void AssertHasSetting(List<string> coverletSettings, string setting)
{
Assert.IsTrue(coverletSettings.Any(coverletSetting => coverletSetting == setting));
}

private void AssertHasEscapedSetting(List<string> coverletSettings, string setting)
{
AssertHasSetting(coverletSettings, CommandLineArguments.AddQuotes(setting));
}
}

public class CoverletConsoleExecuteRequestProvider_Tests
{
[TestCase(0)]
[TestCase(1)]
[TestCase(2)]
Expand All @@ -50,7 +84,7 @@ public void Should_GetCoverletExePath_From_First_That_Returns_Non_Null(int provi

ExecuteRequest GetExecuteRequest(int order)
{
if(order != providingExeProvider)
if (order != providingExeProvider)
{
return null;
}
Expand All @@ -74,13 +108,13 @@ ExecuteRequest GetExecuteRequest(int order)
{
var order = i;
var mockExeProvider = mockExecutors[i];
mockExeProvider.Setup(p => p.GetRequest(coverageProject, coverletSettings)).Returns(GetExecuteRequest(i)).Callback<ICoverageProject,string>((_,__) =>
mockExeProvider.Setup(p => p.GetRequest(coverageProject, coverletSettings)).Returns(GetExecuteRequest(i)).Callback<ICoverageProject, string>((_, __) =>
{
callOrder.Add(order);
});
}

var coverletConsoleUtil = new CoverletConsoleUtil(null, null, mockGlobalExecutor.Object, mockCustomPathExecutor.Object, mockLocalExecutor.Object, mockFCCCoverletConsoleExecutor.Object);
var coverletConsoleUtil = new CoverletConsoleExecuteRequestProvider(mockGlobalExecutor.Object, mockCustomPathExecutor.Object, mockLocalExecutor.Object, mockFCCCoverletConsoleExecutor.Object);

var executeRequest = coverletConsoleUtil.GetExecuteRequest(coverageProject, coverletSettings);

Expand All @@ -94,6 +128,123 @@ ExecuteRequest GetExecuteRequest(int order)
}

}
}

public class CoverletConsoleUtil_Tests
{
private AutoMoqer mocker;
private CoverletConsoleUtil coverletConsoleUtil;
private bool executed;
private readonly List<string> coverletSettings = new List<string> { "setting1", "setting2" };
private readonly ExecuteResponse successfulExecuteResponse = new ExecuteResponse { ExitCode = 3, Output = "Successful output" };

[SetUp]
public void SetUp()
{
executed = false;
mocker = new AutoMoqer();
coverletConsoleUtil = mocker.Create<CoverletConsoleUtil>();
}
[Test]
public void Should_Initilize_IFCCCoverletConsoleExeProvider()
{
var ct = CancellationToken.None;
coverletConsoleUtil.Initialize("appDataFolder", ct);
mocker.Verify<IFCCCoverletConsoleExecutor>(fccExeProvider => fccExeProvider.Initialize("appDataFolder", ct));
}

[Test]
public async Task Should_Execute_The_Request_From_The_Execute_Request_Provider_With_Space_Delimited_Settings()
{
await RunSuccessfullyAsync();

mocker.GetMock<IProcessUtil>().Verify();
}

[Test]
public async Task Should_Log_Settings_Before_Executing()
{
var mockLogger = mocker.GetMock<ILogger>();
mockLogger.Setup(logger => logger.Log(It.IsAny<IEnumerable<string>>())).Callback<IEnumerable<string>>(messages =>
{
var msgList = messages as List<string>;
Assert.Multiple(() =>
{
Assert.That(msgList[0], Is.EqualTo("Coverlet Run (TheProjectName) - Arguments"));
Assert.That(msgList.Skip(1), Is.EqualTo(coverletSettings));
Assert.That(executed, Is.False);
});
});

await RunSuccessfullyAsync();

mockLogger.Verify();
}

[Test]
public void Should_Throw_With_ExecuteResponse_Output_When_ExitCode_Is_Greater_Than_3()
{
var failureExecuteResponse = new ExecuteResponse { ExitCode = 4, Output = "failure message" };
var exception = Assert.ThrowsAsync<Exception>(async() => await RunAsync(failureExecuteResponse));

Assert.That(exception.Message, Is.EqualTo("Error. Exit code: 4"));
}

[Test]
public void Should_Log_With_ExecuteResponse_ExitCode_And_Output_When_ExitCode_Is_Greater_Than_3()
{
var failureExecuteResponse = new ExecuteResponse { ExitCode = 4, Output = "failure message" };

Assert.ThrowsAsync<Exception>(() => RunAsync(failureExecuteResponse));

var mockLogger = mocker.GetMock<ILogger>();
mockLogger.Verify(logger => logger.Log("Coverlet Run (TheProjectName) Error. Exit code: 4", "failure message"));
}

[Test]
public async Task Should_Log_The_ExecuteResponse_Output_On_Success()
{
var mockLogger = mocker.GetMock<ILogger>();
mockLogger.Setup(logger => logger.Log(It.IsAny<string[]>())).Callback<string[]>(messages =>
{
Assert.Multiple(() =>
{
Assert.That(messages, Is.EqualTo(new string[] { "Coverlet Run (TheProjectName) - Output", successfulExecuteResponse.Output }));
Assert.That(executed, Is.True);
});
});

await RunSuccessfullyAsync();

mockLogger.Verify();
}

private async Task RunSuccessfullyAsync()
{
await RunAsync(successfulExecuteResponse);
}

private async Task RunAsync(ExecuteResponse executeResponse)
{
var mockCoverageProject = new Mock<ICoverageProject>();
mockCoverageProject.SetupGet(cp => cp.ProjectName).Returns("TheProjectName");
var coverageProject = mockCoverageProject.Object;
var requestSettings = string.Join(" ", coverletSettings);
var executeRequest = new ExecuteRequest { FilePath = "TheFilePath", Arguments = "TheArguments" };
var cancellationToken = CancellationToken.None;

mocker.Setup<ICoverletExeArgumentsProvider, List<string>>(coverletExeArgumentsProvider => coverletExeArgumentsProvider.GetArguments(coverageProject)).Returns(coverletSettings);
mocker.Setup<ICoverletConsoleExecuteRequestProvider, ExecuteRequest>(
coverletConsoleExecuteRequestProvider => coverletConsoleExecuteRequestProvider.GetExecuteRequest(coverageProject, requestSettings)
).Returns(executeRequest);
var mockProcessUtil = mocker.GetMock<IProcessUtil>();
mockProcessUtil.Setup(processUtil => processUtil.ExecuteAsync(executeRequest, cancellationToken))
.Callback(() => executed = true)
.ReturnsAsync(executeResponse);

await coverletConsoleUtil.RunAsync(coverageProject, cancellationToken);
}

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,18 @@ public async Task Should_Get_Settings_With_IncludeTestAssembly_From_CoverageProj
mockDataCollectorSettingsBuilder.Verify(b => b.WithIncludeTestAssembly(projectIncludeTestAssembly, runSettingsIncludeTestAssembly));
}

[Test]
public async Task Should_Initialize_With_Options_And_Run_Settings_First()
[TestCase(true)]
[TestCase(false)]
public async Task Should_Initialize_With_Options_And_Run_Settings_First(bool runSettingsOnly)
{
var settings = new Mock<IAppOptions>().Object;
mockCoverageProject.Setup(cp => cp.RunSettingsFile).Returns(".runsettings");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("output");
mockCoverageProject.Setup(cp => cp.Settings).Returns(settings);
var mockSettings = new Mock<IAppOptions>();
mockSettings.SetupGet(appOptions => appOptions.RunSettingsOnly).Returns(runSettingsOnly);
mockCoverageProject.Setup(cp => cp.Settings).Returns(mockSettings.Object);

await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
mockDataCollectorSettingsBuilder.Verify(b => b.Initialize(settings, ".runsettings",Path.Combine("output","FCC.runsettings")));
mockDataCollectorSettingsBuilder.Verify(b => b.Initialize(runSettingsOnly, ".runsettings",Path.Combine("output","FCC.runsettings")));

var invocations = mockDataCollectorSettingsBuilder.Invocations.GetEnumerator().ToIEnumerable().ToList();
Assert.AreEqual(invocations.First().Method.Name, nameof(IDataCollectorSettingsBuilder.Initialize));
Expand Down
23 changes: 11 additions & 12 deletions FineCodeCoverageTests/DataCollectorSettingsBuilder_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ public void DeleteRunSettings()

private void Initialize(bool runSettingsOnly = false)
{
var mockCoverageProjectSettings = new Mock<IAppOptions>();
mockCoverageProjectSettings.Setup(o => o.RunSettingsOnly).Returns(runSettingsOnly);
dataCollectorSettingsBuilder.Initialize(mockCoverageProjectSettings.Object, existingRunSettingsPath, generatedRunSettingsPath);
dataCollectorSettingsBuilder.Initialize(runSettingsOnly, existingRunSettingsPath, generatedRunSettingsPath);
}

#region arguments
Expand Down Expand Up @@ -88,7 +86,7 @@ public void Should_Set_ProjectDll_Quoted_When_WithProjectDll()
[Test]
public void Should_Set_RunSettings_As_Quoted_GeneratedRunSettings_When_Initialize()
{
dataCollectorSettingsBuilder.Initialize(null,".runsettings","generated.runsettings");
dataCollectorSettingsBuilder.Initialize(false,".runsettings","generated.runsettings");
Assert.AreEqual(dataCollectorSettingsBuilder.RunSettings,$"--settings {dataCollectorSettingsBuilder.Quote("generated.runsettings")}");
}

Expand Down Expand Up @@ -138,21 +136,22 @@ public void Should_Not_Fallback_To_Options_For_Exclude_If_RunSettingsOnly()
Assert.IsNull(dataCollectorSettingsBuilder.Exclude);
}

[Test]
public void Should_Use_RunSettings_ExcludeByAttribute_If_Present()
[Test] // https://github.com/coverlet-coverage/coverlet/issues/1589
public void Should_Use_RunSettings_ExcludeByAttribute_If_Present_Unqualified()
{
Initialize();
dataCollectorSettingsBuilder.WithExcludeByAttribute(new string[] { "from project" }, "from run settings");
Assert.AreEqual("from run settings", dataCollectorSettingsBuilder.ExcludeByAttribute);
dataCollectorSettingsBuilder.WithExcludeByAttribute(new string[] { "from project" }, "namespace.first,second");
Assert.AreEqual("first,second", dataCollectorSettingsBuilder.ExcludeByAttribute);
}

[Test]
public void Should_Use_Project_ExcludeByAttribute_If_No_RunSettings()
public void Should_Use_Project_ExcludeByAttribute_If_No_RunSettings_Unqualified()
{
dataCollectorSettingsBuilder.WithExcludeByAttribute(new string[] { "first", "second" }, null);
dataCollectorSettingsBuilder.WithExcludeByAttribute(new string[] { "namespace.first", "second" }, null);
Assert.AreEqual(dataCollectorSettingsBuilder.ExcludeByAttribute, "first,second");
}


[Test]
public void Should_Use_Project_ExcludeByAttribute_If_No_RunSettings_Null()
{
Expand Down Expand Up @@ -303,7 +302,7 @@ public void Should_Set_Corresponding_Property_For_RunSettings_Only_Elements()
[TestCaseSource(nameof(BuildReturnsSettingsSource))]
public void Should_Return_Dotnet_Test_Settings_When_Build(Action<DataCollectorSettingsBuilder> setUp, string expectedSettings)
{
dataCollectorSettingsBuilder.Initialize(new Mock<IAppOptions>().Object,null, generatedRunSettingsPath);
dataCollectorSettingsBuilder.Initialize(false,null, generatedRunSettingsPath);
setUp(dataCollectorSettingsBuilder);
Assert.AreEqual(dataCollectorSettingsBuilder.Build(), expectedSettings);
}
Expand Down Expand Up @@ -336,7 +335,7 @@ public void Should_Generate_RunSettings_When_Builds(Action<DataCollectorSettings
XDocument.Parse(existingRunSettings).Save(existingRunSettingsPath);
}

dataCollectorSettingsBuilder.Initialize(null,existingRunSettings == null ? null : existingRunSettingsPath, generatedRunSettingsPath);
dataCollectorSettingsBuilder.Initialize(false,existingRunSettings == null ? null : existingRunSettingsPath, generatedRunSettingsPath);
dataCollectorSettingsBuilder.Build();


Expand Down

0 comments on commit a5af270

Please sign in to comment.