Skip to content

Commit

Permalink
think maybe I'm happy now?
Browse files Browse the repository at this point in the history
  • Loading branch information
david-driscoll committed Nov 19, 2024
1 parent c617a30 commit 8a44582
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 128 deletions.
51 changes: 34 additions & 17 deletions src/Nuke/IHaveCodeCoverage.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Xml.Linq;
using Nuke.Common.IO;

namespace Rocket.Surgery.Nuke;
Expand All @@ -20,11 +21,13 @@ public interface IHaveCodeCoverage : IHaveArtifacts
?? TryGetValue(() => CoverageDirectory)
?? NukeBuild.RootDirectory / "coverage";

public IEnumerable<string> IncludeModulePaths => [];
public IEnumerable<string> ExcludeModulePaths => [];
public IEnumerable<string> IncludeAttributes => [];
public static IEnumerable<string> DefaultIncludeModulePaths => [];
public static IEnumerable<string> DefaultExcludeModulePaths => [];
public static IEnumerable<string> DefaultIncludeSources => [];
public static IEnumerable<string> DefaultExcludeSources => [];
public static IEnumerable<string> DefaultIncludeAttributes => [];

Check warning on line 28 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L24-L28

Added lines #L24 - L28 were not covered by tests

public IEnumerable<string> ExcludeAttributes =>
public static IEnumerable<string> DefaultExcludeAttributes =>
[
"System.Diagnostics.DebuggerHiddenAttribute",
"System.Diagnostics.DebuggerNonUserCodeAttribute",
Expand All @@ -33,23 +36,37 @@ public interface IHaveCodeCoverage : IHaveArtifacts
"System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute",
];

public IEnumerable<string> IncludeNamespaces => [];
public static IEnumerable<string> DefaultIncludeNamespaces => [];

Check warning on line 39 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L39

Added line #L39 was not covered by tests

public IEnumerable<string> ExcludeNamespaces =>
public static IEnumerable<string> DefaultExcludeNamespaces =>
[
"Bogus.",
"FakeItEasy.",
"Moq.",
"NSubstitute.",
"Verify.",
"XUnit.",
"TUnit.",
"Bogus",
"FakeItEasy",
"Moq",
"NSubstitute",
"Verify",
"XUnit",
"TUnit",

Check warning on line 49 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L43-L49

Added lines #L43 - L49 were not covered by tests
"Microsoft.",
"System.",
"JetBrains.",
"DryIoc.",
"Nuke.",
"FluentAssertions.",
"Serilog.",
"DryIoc",
"Nuke",
"FluentAssertions",
"Serilog",

Check warning on line 56 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L53-L56

Added lines #L53 - L56 were not covered by tests
];

public IEnumerable<string> IncludeNamespaces => DefaultIncludeNamespaces;
public IEnumerable<string> ExcludeNamespaces => DefaultExcludeNamespaces;
public IEnumerable<string> IncludeAttributes => DefaultIncludeAttributes;
public IEnumerable<string> ExcludeAttributes => DefaultExcludeAttributes;
public IEnumerable<string> IncludeSources => DefaultIncludeSources;
public IEnumerable<string> ExcludeSources => DefaultExcludeSources;
public IEnumerable<string> IncludeModulePaths => DefaultIncludeModulePaths;
public IEnumerable<string> ExcludeModulePaths => DefaultExcludeModulePaths;

Check warning on line 66 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L59-L66

Added lines #L59 - L66 were not covered by tests

public XDocument CustomizeCoverageRunSettings(XDocument document)
{
return document;
}

Check warning on line 71 in src/Nuke/IHaveCodeCoverage.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/IHaveCodeCoverage.cs#L69-L71

Added lines #L69 - L71 were not covered by tests
}
50 changes: 36 additions & 14 deletions src/Nuke/ITriggerCodeCoverageReports.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Nuke.Common.IO;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.ReportGenerator;
using Rocket.Surgery.Nuke.ProjectModel;

// ReSharper disable SuspiciousTypeConversion.Global

Expand All @@ -13,7 +14,7 @@ namespace Rocket.Surgery.Nuke;
/// This causes code coverage to trigger
/// </remarks>
[PublicAPI]
public interface ITriggerCodeCoverageReports : IHaveCodeCoverage, IHaveTestTarget, IHaveTestArtifacts, ITrigger
public interface ITriggerCodeCoverageReports : IHaveCodeCoverage, IHaveTestTarget, IHaveTestArtifacts, ITrigger, IHaveSolution
{
/// <summary>
/// The input reports
Expand Down Expand Up @@ -89,17 +90,38 @@ public interface ITriggerCodeCoverageReports : IHaveCodeCoverage, IHaveTestTarge
/// </summary>
/// <param name="settings"></param>
/// <returns></returns>
protected ReportGeneratorSettings Defaults(ReportGeneratorSettings settings) => ( this switch
{
IHaveGitVersion gitVersion => settings.SetTag(
gitVersion.GitVersion.InformationalVersion
),
IHaveGitRepository { GitRepository: { } } gitRepository => settings
.SetTag(gitRepository.GitRepository.Head),
_ => settings,
}
)
.SetReports(InputReports)
.SetSourceDirectories(NukeBuild.RootDirectory)
.SetFramework(Constants.ReportGeneratorFramework);
protected ReportGeneratorSettings Defaults(ReportGeneratorSettings settings)
=> ( this switch
{
IHaveGitVersion gitVersion => settings.SetTag(
gitVersion.GitVersion.InformationalVersion
),
IHaveGitRepository { GitRepository: { } } gitRepository => settings
.SetTag(gitRepository.GitRepository.Head),
_ => settings,
}
)
.SetReports(InputReports)
.SetSourceDirectories(NukeBuild.RootDirectory)
.SetFramework(Constants.ReportGeneratorFramework)
// this is more or less a hack / compromise because
// I was unable to coverage to exclude everything in a given assembly by default.
.AddAssemblyFilters(
Solution
.AnalyzeAllProjects()
.Select(z => z.GetProperty("AssemblyName") ?? "")
.Where(z => !string.IsNullOrWhiteSpace(z))
.Distinct()
.Select(z => "+" + z)
)
.AddAssemblyFilters(
Solution
.AnalyzeAllProjects()
.SelectMany(z => z.PackageReferences)
.Select(z => z.Name)
.Where(z => !string.IsNullOrWhiteSpace(z))
.Distinct()
.Select(z => "-" + z)
)

Check warning on line 125 in src/Nuke/ITriggerCodeCoverageReports.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/ITriggerCodeCoverageReports.cs#L95-L125

Added lines #L95 - L125 were not covered by tests
;
}
112 changes: 66 additions & 46 deletions src/Nuke/TestMethodExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Immutable;
using System.Xml.Linq;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Rocket.Surgery.Nuke.DotNetCore;
using Rocket.Surgery.Nuke.ProjectModel;

namespace Rocket.Surgery.Nuke;

Expand All @@ -19,7 +22,7 @@ public static class TestMethodExtensions
// ReSharper disable once IdentifierTypo
// ReSharper disable once StringLiteralTypo
public static ITargetDefinition EnsureRunSettingsExists<T>(this ITargetDefinition target, T build)
where T : IHaveCodeCoverage, IComprehendTests
where T : IHaveCodeCoverage, IComprehendTests, IHaveSolution
{
return target.Executes(
async () =>
Expand All @@ -38,28 +41,46 @@ await typeof(ICanTestWithDotNetCore)
.GetManifestResourceStream("Rocket.Surgery.Nuke.default.runsettings")!.CopyToAsync(tempFile);
}

var projects = build
.Solution.AnalyzeAllProjects()
.ToImmutableArray();
var includeNames = projects
.Select(z => z.GetProperty("AssemblyName") ?? "")
.Where(z => !string.IsNullOrWhiteSpace(z))
.Distinct()
.Select(z => ( z + ".dll" ).Replace(".", "\\."));
var excludePackages = projects
.SelectMany(z => z.PackageReferences)
.Select(z => z.Name)
.Where(z => !string.IsNullOrWhiteSpace(z))
.Distinct()
.Select(z => ( z + ".dll" ).Replace(".", "\\."));


Check warning on line 59 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L44-L59

Added lines #L44 - L59 were not covered by tests
ManageRunSettings(
build,

Check warning on line 61 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L61

Added line #L61 was not covered by tests
runsettings,
build.IncludeModulePaths,
build.ExcludeModulePaths,
build.IncludeAttributes,
build.ExcludeAttributes,
build.IncludeNamespaces,
build.ExcludeNamespaces
(
build.IncludeModulePaths.Union(includeNames),
build.ExcludeModulePaths .Union(excludePackages)
),
( build.IncludeAttributes, build.ExcludeAttributes ),
( build.IncludeNamespaces, build.ExcludeNamespaces ),
( build.IncludeSources, build.ExcludeSources )

Check warning on line 69 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L63-L69

Added lines #L63 - L69 were not covered by tests
);
}
);
}

private static void ManageRunSettings(
private static void ManageRunSettings<T>(
T build,
AbsolutePath runsettingsPath,
IEnumerable<string> includeModulePaths,
IEnumerable<string> excludeModulePaths,
IEnumerable<string> includeAttributes,
IEnumerable<string> excludeAttributes,
IEnumerable<string> includeNamespaces,
IEnumerable<string> excludeNamespaces
(IEnumerable<string> include, IEnumerable<string> exclude) modulePaths,
(IEnumerable<string> include, IEnumerable<string> exclude) attributes,
(IEnumerable<string> include, IEnumerable<string> exclude) namespaces,
(IEnumerable<string> include, IEnumerable<string> exclude) sources
)
where T : IHaveCodeCoverage, IComprehendTests
{
var doc = XDocument.Load(runsettingsPath);

Expand All @@ -81,28 +102,29 @@ IEnumerable<string> excludeNamespaces
dataCollector.Element("Configuration")?.Add(codeCoverage);
}

AddIncludeItems(codeCoverage, "ModulePaths", "ModulePath", includeModulePaths);
AddExcludeItems(codeCoverage, "ModulePaths", "ModulePath", excludeModulePaths);
AddIncludeItems(codeCoverage, "Attributes", "Attribute", includeAttributes.Select(TransformAttribute));
AddExcludeItems(codeCoverage, "Attributes", "Attribute", excludeAttributes.Select(TransformAttribute));
AddIncludeItems(codeCoverage, "Functions", "Function", includeNamespaces.Select(TransformNamespace));
AddExcludeItems(codeCoverage, "Functions", "Function", excludeNamespaces.Select(TransformNamespace));
AddItems(codeCoverage, "Attributes", "Attribute", transform(attributes, transformAttribute));
AddItems(codeCoverage, "Functions", "Function", transform(namespaces, transformNamespace));
AddItems(codeCoverage, "ModulePaths", "ModulePath", transform(modulePaths, transformModulePath));
AddItems(codeCoverage, "Sources", "Source", sources);

Check warning on line 108 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L108

Added line #L108 was not covered by tests

build.CustomizeCoverageRunSettings(doc);

Check warning on line 110 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L110

Added line #L110 was not covered by tests

DistinctAndOrganize(codeCoverage, "ModulePaths");
DistinctAndOrganize(codeCoverage, "Attributes");
DistinctAndOrganize(codeCoverage, "Functions");
DistinctAndOrganize(codeCoverage, "ModulePaths");
DistinctAndOrganize(codeCoverage, "Sources");

Check warning on line 115 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L114-L115

Added lines #L114 - L115 were not covered by tests

doc.Save(runsettingsPath);

static string TransformAttribute(string ns)
{
return $"^{ns.Replace(".", "\\.")}$";
}
static (IEnumerable<string> include, IEnumerable<string> exclude) transform(
(IEnumerable<string> include, IEnumerable<string> exclude) attributes,
Func<string, IEnumerable<string>> transformer
) => ( attributes.include.SelectMany(transformer), attributes.exclude.SelectMany(transformer) );

static string TransformNamespace(string ns)
{
return $"^{ns.Replace(".", "\\.")}.*";
}

static IEnumerable<string> transformAttribute(string attr) => [$"^{attr.Replace(".", "\\.")}$"];
static IEnumerable<string> transformModulePath(string ns) => [$".*{ns}"];
static IEnumerable<string> transformNamespace(string ns) => [$"^{ns.Replace(".", "\\.")}.*"];
}

private static XElement EnsureElement(XElement parent, string name)
Expand All @@ -117,47 +139,45 @@ private static XElement EnsureElement(XElement parent, string name)
return element;
}

private static void AddIncludeItems(XElement parent, string parentName, string childName, IEnumerable<string> values)
private static void AddItems(XElement parent, string parentName, string childName, (IEnumerable<string> include, IEnumerable<string> exclude) values)
{
var parentElement = EnsureElement(parent, parentName);
var element = EnsureElement(parentElement, "Include");
var include = EnsureElement(parentElement, "Include");
var exclude = EnsureElement(parentElement, "Exclude");

Check warning on line 146 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L145-L146

Added lines #L145 - L146 were not covered by tests

element.RemoveAll();
foreach (var value in values)
include.RemoveAll();
exclude.RemoveAll();

Check warning on line 149 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L148-L149

Added lines #L148 - L149 were not covered by tests

foreach (var value in values.include)
{
element.Add(new XElement(childName, value));
include.Add(new XElement(childName, value));

Check warning on line 153 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L153

Added line #L153 was not covered by tests
}
}

private static void AddExcludeItems(XElement parent, string parentName, string childName, IEnumerable<string> values)
{
var parentElement = EnsureElement(parent, parentName);
var element = EnsureElement(parentElement, "Exclude");

element.RemoveAll();
foreach (var value in values)
foreach (var value in values.exclude)
{
element.Add(new XElement(childName, value));
exclude.Add(new XElement(childName, value));

Check warning on line 158 in src/Nuke/TestMethodExtensions.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/TestMethodExtensions.cs#L158

Added line #L158 was not covered by tests
}
}

private static void DistinctAndOrganize(XElement parent, string parentName)
{
var element = EnsureElement(parent, parentName);
if (element.Element("Include") is { } include)
if (parent.Element(parentName) is not { } item) return;
if (item.Element("Include") is { } include)
{
var values = include.Elements().DistinctBy(z => z.Value).OrderBy(x => x.Value).ToArray();
include.RemoveAll();
include.Add([..values]);
if (!include.Elements().Any()) include.Remove();
}

if (element.Element("Exclude") is { } exclude)
if (item.Element("Exclude") is { } exclude)
{
var values = exclude.Elements().DistinctBy(z => z.Value).OrderBy(x => x.Value).ToArray();
exclude.RemoveAll();
exclude.Add([..values]);
if (!exclude.Elements().Any()) exclude.Remove();
}

if (!item.Elements().Any()) item.Remove();
}
}
2 changes: 1 addition & 1 deletion src/Nuke/Xamarin/ICanTestXamarin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public interface ICanTestXamarin : IHaveTestTarget,
.SetLoggers("trx")
.SetProperty("CollectCoverage", "true")
.SetProperty(
"DeterministicSourcePaths",
"DeterministicSourcePaths",

Check warning on line 40 in src/Nuke/Xamarin/ICanTestXamarin.cs

View check run for this annotation

Codecov / codecov/patch

src/Nuke/Xamarin/ICanTestXamarin.cs#L40

Added line #L40 was not covered by tests
"false"
) // DeterministicSourcePaths being true breaks coverlet!
.SetProperty("CoverageDirectory", CoverageDirectory)
Expand Down
44 changes: 7 additions & 37 deletions src/Nuke/default.runsettings
Original file line number Diff line number Diff line change
@@ -1,47 +1,17 @@
<RunSettings>
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage"
uri="datacollector://Microsoft/CodeCoverage/2.0"
assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<DataCollector friendlyName="Code Coverage">
<Configuration>
<Format>Cobertura</Format>
<CodeCoverage>
<EnableStaticManagedInstrumentation>True</EnableStaticManagedInstrumentation>
<EnableDynamicManagedInstrumentation>True</EnableDynamicManagedInstrumentation>
<ModulePaths>
<Exclude>
<ModulePath>.*DryIoc.dll</ModulePath>
<ModulePath>.*FluentAssertions.dll</ModulePath>
</Exclude>
</ModulePaths>
<Attributes>
<Exclude>
<Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>
<Attribute>^System\.Diagnostics\.DebuggerNonUserCodeAttribute$</Attribute>
<Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
<Attribute>^System\.Runtime\.CompilerServices\.CompilerGeneratedAttribute$</Attribute>
<Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
</Exclude>
</Attributes>
<Functions>
<Exclude>
<Function>^Bogus\..*</Function>
<Function>^FakeItEasy\..*</Function>
<Function>^Moq\..*</Function>
<Function>^NSubstitute\..*</Function>
<Function>^Verify\..*</Function>
<Function>^XUnit\..*</Function>
<Function>^TUnit\..*</Function>
<Function>^Microsoft\..*</Function>
<Function>^System\..*</Function>
<Function>^JetBrains\..*</Function>
<Function>^DryIoc\..*</Function>
<Function>^Nuke\..*</Function>
<Function>^FluentAssertions\..*</Function>
<Function>^Serilog\..*</Function>
</Exclude>
</Functions>
<Attributes />
<Functions />
<Sources />
<ModulePaths/>
</CodeCoverage>
</Configuration>
</DataCollector>
Expand Down
Loading

0 comments on commit 8a44582

Please sign in to comment.