From c745dbca3cc12433fa145dcc57581ff6d7dce712 Mon Sep 17 00:00:00 2001 From: benjaminZale Date: Sun, 14 Mar 2021 12:43:29 -0400 Subject: [PATCH] Implementation of Npath complexity for the OpenCover reports (#1058) Implementation of Npath complexity for the OpenCover reports --- src/coverlet.core/CoverageSummary.cs | 34 +++++++++++++++++++ .../Reporters/OpenCoverReporter.cs | 3 +- .../Reporters/OpenCoverReporterTests.cs | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/coverlet.core/CoverageSummary.cs b/src/coverlet.core/CoverageSummary.cs index 5a64e0b..188e204 100644 --- a/src/coverlet.core/CoverageSummary.cs +++ b/src/coverlet.core/CoverageSummary.cs @@ -73,6 +73,40 @@ namespace Coverlet.Core return details; } + public int CalculateNpathComplexity(IList branches) + { + // Adapted from OpenCover see https://github.com/OpenCover/opencover/blob/master/main/OpenCover.Framework/Persistance/BasePersistance.cs#L419 + if (!branches.Any()) + { + return 0; + } + + var paths = new Dictionary(); + foreach (var branch in branches) + { + if (!paths.TryGetValue(branch.Offset, out int count)) + { + count = 0; + } + paths[branch.Offset] = ++count; + } + + int npath = 1; + foreach (var branchPoints in paths.Values) + { + try + { + npath = checked(npath * branchPoints); + } + catch (OverflowException) + { + npath = int.MaxValue; + break; + } + } + return npath; + } + public int CalculateCyclomaticComplexity(IList branches) { return Math.Max(1, branches.Count); diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index ac31f4d..6d4c7b6 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -78,11 +78,12 @@ namespace Coverlet.Core.Reporters var methLineCoverage = summary.CalculateLineCoverage(meth.Value.Lines); var methBranchCoverage = summary.CalculateBranchCoverage(meth.Value.Branches); var methCyclomaticComplexity = summary.CalculateCyclomaticComplexity(meth.Value.Branches); + var methNpathComplexity = summary.CalculateNpathComplexity(meth.Value.Branches); XElement method = new XElement("Method"); method.Add(new XAttribute("cyclomaticComplexity", methCyclomaticComplexity.ToString())); - method.Add(new XAttribute("nPathComplexity", "0")); + method.Add(new XAttribute("nPathComplexity", methCyclomaticComplexity.ToString())); method.Add(new XAttribute("sequenceCoverage", methLineCoverage.Percent.ToString("G", CultureInfo.InvariantCulture))); method.Add(new XAttribute("branchCoverage", methBranchCoverage.Percent.ToString("G", CultureInfo.InvariantCulture))); method.Add(new XAttribute("isConstructor", meth.Key.Contains("ctor").ToString())); diff --git a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs index 75698b6..828e4ab 100644 --- a/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/OpenCoverReporterTests.cs @@ -27,6 +27,7 @@ namespace Coverlet.Core.Reporters.Tests XDocument doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(report))); Assert.Empty(doc.Descendants().Attributes("sequenceCoverage").Where(v => v.Value != "33.33")); Assert.Empty(doc.Descendants().Attributes("branchCoverage").Where(v => v.Value != "25")); + Assert.Empty(doc.Descendants().Attributes("nPathComplexity").Where(v => v.Value != "4")); } [Fact]