From 48adc51a7af9c3119c2cf10d5dd1fe4e90516567 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Tue, 17 Apr 2018 10:03:49 +0100 Subject: [PATCH 1/6] fix lcov reporter output --- src/coverlet.core/Reporters/LcovReporter.cs | 2 +- test/coverlet.core.tests/Reporters/LcovReporterTests.cs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/Reporters/LcovReporter.cs b/src/coverlet.core/Reporters/LcovReporter.cs index 44d63dcd3..85b6e6344 100644 --- a/src/coverlet.core/Reporters/LcovReporter.cs +++ b/src/coverlet.core/Reporters/LcovReporter.cs @@ -23,7 +23,7 @@ public string Report(CoverageResult result) { foreach (var line in method.Value) { - lcov.Add($"DA:{line.Key},{line.Value}"); + lcov.Add($"DA:{line.Key},{line.Value.Hits}"); } } } diff --git a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs index a7b8e67d3..bf28cfe12 100644 --- a/test/coverlet.core.tests/Reporters/LcovReporterTests.cs +++ b/test/coverlet.core.tests/Reporters/LcovReporterTests.cs @@ -23,7 +23,13 @@ public void TestReport() result.Modules.Add("module", documents); LcovReporter reporter = new LcovReporter(); - Assert.NotEqual(string.Empty, reporter.Report(result)); + string report = reporter.Report(result); + + Assert.NotEmpty(report); + Assert.Equal("SF:doc.cs", report.Split(Environment.NewLine)[0]); + Assert.Equal("DA:1,1", report.Split(Environment.NewLine)[1]); + Assert.Equal("DA:2,0", report.Split(Environment.NewLine)[2]); + Assert.Equal("end_of_record", report.Split(Environment.NewLine)[3]); } } } \ No newline at end of file From 0f8741e9d58b37f32f49e4b589b482b290297430 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Tue, 17 Apr 2018 11:29:10 +0100 Subject: [PATCH 2/6] remove need for overriding StringWriter class --- .../Reporters/OpenCoverReporter.cs | 285 +++++++++--------- 1 file changed, 136 insertions(+), 149 deletions(-) diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index f2f7e5c27..196efd036 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -3,17 +3,12 @@ using System.IO; using System.Linq; using System.Text; -using System.Xml; +using System.Xml.Linq; namespace Coverlet.Core.Reporters { public class OpenCoverReporter : IReporter { - private sealed class Utf8StringWriter : StringWriter - { - public override Encoding Encoding => Encoding.UTF8; - } - public string Format => "opencover"; public string Extension => "xml"; @@ -21,11 +16,10 @@ private sealed class Utf8StringWriter : StringWriter public string Report(CoverageResult result) { CoverageSummary summary = new CoverageSummary(); - XmlDocument xml = new XmlDocument(); - XmlElement coverage = xml.CreateElement("CoverageSession"); - XmlElement coverageSummary = xml.CreateElement("Summary"); - - XmlElement modules = xml.CreateElement("Modules"); + XDocument xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + XElement coverage = new XElement("CoverageSession"); + XElement coverageSummary = new XElement("Summary"); + XElement modules = new XElement("Modules"); int numSequencePoints = 0, numBranchPoints = 0, numClasses = 0, numMethods = 0; int visitedSequencePoints = 0, visitedBranchPoints = 0, visitedClasses = 0, visitedMethods = 0; @@ -34,109 +28,102 @@ public string Report(CoverageResult result) foreach (var mod in result.Modules) { - XmlElement module = xml.CreateElement("Module"); - module.SetAttribute("hash", Guid.NewGuid().ToString().ToUpper()); - - XmlElement path = xml.CreateElement("ModulePath"); - path.AppendChild(xml.CreateTextNode(mod.Key)); + XElement module = new XElement("Module"); + module.Add(new XAttribute("hash", Guid.NewGuid().ToString().ToUpper())); - XmlElement time = xml.CreateElement("ModuleTime"); - time.AppendChild(xml.CreateTextNode(DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss"))); + XElement path = new XElement("ModulePath", mod.Key); + XElement time = new XElement("ModuleTime", DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss")); + XElement name = new XElement("ModuleName", Path.GetFileNameWithoutExtension(mod.Key)); - XmlElement name = xml.CreateElement("ModuleName"); - name.AppendChild(xml.CreateTextNode(Path.GetFileNameWithoutExtension(mod.Key))); + module.Add(path); + module.Add(time); + module.Add(name); - module.AppendChild(path); - module.AppendChild(time); - module.AppendChild(name); + XElement files = new XElement("Files"); + XElement classes = new XElement("Classes"); - XmlElement files = xml.CreateElement("Files"); - XmlElement classes = xml.CreateElement("Classes"); - foreach (var doc in mod.Value) { - XmlElement file = xml.CreateElement("File"); - file.SetAttribute("uid", i.ToString()); - file.SetAttribute("fullPath", doc.Key); - files.AppendChild(file); + XElement file = new XElement("File"); + file.Add(new XAttribute("uid", i.ToString())); + file.Add(new XAttribute("fullPath", doc.Key)); + files.Add(file); foreach (var cls in doc.Value) { - XmlElement @class = xml.CreateElement("Class"); - XmlElement classSummary = xml.CreateElement("Summary"); + XElement @class = new XElement("Class"); + XElement classSummary = new XElement("Summary"); - XmlElement className = xml.CreateElement("FullName"); - className.AppendChild(xml.CreateTextNode(cls.Key)); + XElement className = new XElement("FullName", cls.Key); - XmlElement methods = xml.CreateElement("Methods"); + XElement methods = new XElement("Methods"); int j = 0; var classVisited = false; foreach (var meth in cls.Value) { - XmlElement method = xml.CreateElement("Method"); - - method.SetAttribute("cyclomaticComplexity", "0"); - method.SetAttribute("nPathComplexity", "0"); - method.SetAttribute("sequenceCoverage", summary.CalculateLineCoverage(meth.Value).ToString()); - method.SetAttribute("branchCoverage", summary.CalculateBranchCoverage(meth.Value).ToString()); - method.SetAttribute("isConstructor", meth.Key.Contains("ctor").ToString()); - method.SetAttribute("isGetter", meth.Key.Contains("get_").ToString()); - method.SetAttribute("isSetter", meth.Key.Contains("set_").ToString()); - method.SetAttribute("isStatic", (!meth.Key.Contains("get_") || !meth.Key.Contains("set_")).ToString()); - - XmlElement methodName = xml.CreateElement("Name"); - methodName.AppendChild(xml.CreateTextNode(meth.Key)); - - XmlElement fileRef = xml.CreateElement("FileRef"); - fileRef.SetAttribute("uid", i.ToString()); - - XmlElement methodPoint = xml.CreateElement("MethodPoint"); - methodPoint.SetAttribute("vc", meth.Value.Select(l => l.Value.Hits).Sum().ToString()); - methodPoint.SetAttribute("upsid", "0"); - methodPoint.SetAttribute("type", "xsi", "SequencePoint"); - methodPoint.SetAttribute("ordinal", j.ToString()); - methodPoint.SetAttribute("offset", j.ToString()); - methodPoint.SetAttribute("sc", "0"); - methodPoint.SetAttribute("sl", meth.Value.First().Key.ToString()); - methodPoint.SetAttribute("ec", "1"); - methodPoint.SetAttribute("el", meth.Value.Last().Key.ToString()); - methodPoint.SetAttribute("bec", "0"); - methodPoint.SetAttribute("bev", "0"); - methodPoint.SetAttribute("fileid", i.ToString()); + XElement method = new XElement("Method"); + + method.Add(new XAttribute("cyclomaticComplexity", "0")); + method.Add(new XAttribute("nPathComplexity", "0")); + method.Add(new XAttribute("sequenceCoverage", summary.CalculateLineCoverage(meth.Value).ToString())); + method.Add(new XAttribute("branchCoverage", summary.CalculateBranchCoverage(meth.Value).ToString())); + method.Add(new XAttribute("isConstructor", meth.Key.Contains("ctor").ToString())); + method.Add(new XAttribute("isGetter", meth.Key.Contains("get_").ToString())); + method.Add(new XAttribute("isSetter", meth.Key.Contains("set_").ToString())); + method.Add(new XAttribute("isStatic", (!meth.Key.Contains("get_") || !meth.Key.Contains("set_")).ToString())); + + XElement methodName = new XElement("Name", meth.Key); + + XElement fileRef = new XElement("FileRef"); + fileRef.Add(new XAttribute("uid", i.ToString())); + + XElement methodPoint = new XElement("MethodPoint"); + methodPoint.Add(new XAttribute("vc", meth.Value.Select(l => l.Value.Hits).Sum().ToString())); + methodPoint.Add(new XAttribute("upsid", "0")); + methodPoint.Add(new XAttribute(XName.Get("type", "xsi"), "SequencePoint")); + methodPoint.Add(new XAttribute("ordinal", j.ToString())); + methodPoint.Add(new XAttribute("offset", j.ToString())); + methodPoint.Add(new XAttribute("sc", "0")); + methodPoint.Add(new XAttribute("sl", meth.Value.First().Key.ToString())); + methodPoint.Add(new XAttribute("ec", "1")); + methodPoint.Add(new XAttribute("el", meth.Value.Last().Key.ToString())); + methodPoint.Add(new XAttribute("bec", "0")); + methodPoint.Add(new XAttribute("bev", "0")); + methodPoint.Add(new XAttribute("fileid", i.ToString())); // They're really just lines - XmlElement sequencePoints = xml.CreateElement("SequencePoints"); - XmlElement branchPoints = xml.CreateElement("BranchPoints"); - XmlElement methodSummary = xml.CreateElement("Summary"); + XElement sequencePoints = new XElement("SequencePoints"); + XElement branchPoints = new XElement("BranchPoints"); + XElement methodSummary = new XElement("Summary"); int k = 0; int kBr = 0; var methodVisited = false; foreach (var lines in meth.Value) { - XmlElement sequencePoint = xml.CreateElement("SequencePoint"); - sequencePoint.SetAttribute("vc", lines.Value.Hits.ToString()); - sequencePoint.SetAttribute("upsid", lines.Key.ToString()); - sequencePoint.SetAttribute("ordinal", k.ToString()); - sequencePoint.SetAttribute("sl", lines.Key.ToString()); - sequencePoint.SetAttribute("sc", "1"); - sequencePoint.SetAttribute("el", lines.Key.ToString()); - sequencePoint.SetAttribute("ec", "2"); - sequencePoint.SetAttribute("bec", "0"); - sequencePoint.SetAttribute("bev", "0"); - sequencePoint.SetAttribute("fileid", i.ToString()); - sequencePoints.AppendChild(sequencePoint); + XElement sequencePoint = new XElement("SequencePoint"); + sequencePoint.Add(new XAttribute("vc", lines.Value.Hits.ToString())); + sequencePoint.Add(new XAttribute("upsid", lines.Key.ToString())); + sequencePoint.Add(new XAttribute("ordinal", k.ToString())); + sequencePoint.Add(new XAttribute("sl", lines.Key.ToString())); + sequencePoint.Add(new XAttribute("sc", "1")); + sequencePoint.Add(new XAttribute("el", lines.Key.ToString())); + sequencePoint.Add(new XAttribute("ec", "2")); + sequencePoint.Add(new XAttribute("bec", "0")); + sequencePoint.Add(new XAttribute("bev", "0")); + sequencePoint.Add(new XAttribute("fileid", i.ToString())); + sequencePoints.Add(sequencePoint); if (lines.Value.IsBranchPoint) { - XmlElement branchPoint = xml.CreateElement("BranchPoint"); - branchPoint.SetAttribute("vc", lines.Value.Hits.ToString()); - branchPoint.SetAttribute("upsid", lines.Key.ToString()); - branchPoint.SetAttribute("ordinal", kBr.ToString()); - branchPoint.SetAttribute("sl", lines.Key.ToString()); - branchPoint.SetAttribute("fileid", i.ToString()); - branchPoints.AppendChild(branchPoint); + XElement branchPoint = new XElement("BranchPoint"); + branchPoint.Add(new XAttribute("vc", lines.Value.Hits.ToString())); + branchPoint.Add(new XAttribute("upsid", lines.Key.ToString())); + branchPoint.Add(new XAttribute("ordinal", kBr.ToString())); + branchPoint.Add(new XAttribute("sl", lines.Key.ToString())); + branchPoint.Add(new XAttribute("fileid", i.ToString())); + branchPoints.Add(branchPoint); kBr++; numBranchPoints++; } @@ -158,27 +145,27 @@ public string Report(CoverageResult result) if (methodVisited) visitedMethods++; - methodSummary.SetAttribute("numSequencePoints", meth.Value.Count().ToString()); - methodSummary.SetAttribute("visitedSequencePoints", meth.Value.Where(l => l.Value.Hits > 0).Count().ToString()); - methodSummary.SetAttribute("numBranchPoints", meth.Value.Where(l => l.Value.IsBranchPoint).Count().ToString()); - methodSummary.SetAttribute("visitedBranchPoints", meth.Value.Where(l => l.Value.IsBranchPoint && l.Value.Hits > 0).Count().ToString()); - methodSummary.SetAttribute("sequenceCoverage", summary.CalculateLineCoverage(meth.Value).ToString()); - methodSummary.SetAttribute("branchCoverage", summary.CalculateBranchCoverage(meth.Value).ToString()); - methodSummary.SetAttribute("maxCyclomaticComplexity", "0"); - methodSummary.SetAttribute("minCyclomaticComplexity", "0"); - methodSummary.SetAttribute("visitedClasses", "0"); - methodSummary.SetAttribute("numClasses", "0"); - methodSummary.SetAttribute("visitedMethods", methodVisited ? "1" : "0"); - methodSummary.SetAttribute("numMethods", "1"); - - method.AppendChild(methodSummary); - method.AppendChild(xml.CreateElement("MetadataToken")); - method.AppendChild(methodName); - method.AppendChild(fileRef); - method.AppendChild(sequencePoints); - method.AppendChild(branchPoints); - method.AppendChild(methodPoint); - methods.AppendChild(method); + methodSummary.Add(new XAttribute("numSequencePoints", meth.Value.Count().ToString())); + methodSummary.Add(new XAttribute("visitedSequencePoints", meth.Value.Where(l => l.Value.Hits > 0).Count().ToString())); + methodSummary.Add(new XAttribute("numBranchPoints", meth.Value.Where(l => l.Value.IsBranchPoint).Count().ToString())); + methodSummary.Add(new XAttribute("visitedBranchPoints", meth.Value.Where(l => l.Value.IsBranchPoint && l.Value.Hits > 0).Count().ToString())); + methodSummary.Add(new XAttribute("sequenceCoverage", summary.CalculateLineCoverage(meth.Value).ToString())); + methodSummary.Add(new XAttribute("branchCoverage", summary.CalculateBranchCoverage(meth.Value).ToString())); + methodSummary.Add(new XAttribute("maxCyclomaticComplexity", "0")); + methodSummary.Add(new XAttribute("minCyclomaticComplexity", "0")); + methodSummary.Add(new XAttribute("visitedClasses", "0")); + methodSummary.Add(new XAttribute("numClasses", "0")); + methodSummary.Add(new XAttribute("visitedMethods", methodVisited ? "1" : "0")); + methodSummary.Add(new XAttribute("numMethods", "1")); + + method.Add(methodSummary); + method.Add(new XElement("MetadataToken")); + method.Add(methodName); + method.Add(fileRef); + method.Add(sequencePoints); + method.Add(branchPoints); + method.Add(methodPoint); + methods.Add(method); j++; } @@ -186,53 +173,53 @@ public string Report(CoverageResult result) if (classVisited) visitedClasses++; - classSummary.SetAttribute("numSequencePoints", cls.Value.Select(c => c.Value.Count).Sum().ToString()); - classSummary.SetAttribute("visitedSequencePoints", cls.Value.Select(c => c.Value.Where(l => l.Value.Hits > 0).Count()).Sum().ToString()); - classSummary.SetAttribute("numBranchPoints", cls.Value.Select(c => c.Value.Count(l => l.Value.IsBranchPoint)).Sum().ToString()); - classSummary.SetAttribute("visitedBranchPoints", cls.Value.Select(c => c.Value.Where(l => l.Value.Hits > 0 && l.Value.IsBranchPoint).Count()).Sum().ToString()); - classSummary.SetAttribute("sequenceCoverage", summary.CalculateLineCoverage(cls.Value).ToString()); - classSummary.SetAttribute("branchCoverage", summary.CalculateBranchCoverage(cls.Value).ToString()); - classSummary.SetAttribute("maxCyclomaticComplexity", "0"); - classSummary.SetAttribute("minCyclomaticComplexity", "0"); - classSummary.SetAttribute("visitedClasses", classVisited ? "1" : "0"); - classSummary.SetAttribute("numClasses", "1"); - classSummary.SetAttribute("visitedMethods", "0"); - classSummary.SetAttribute("numMethods", cls.Value.Count.ToString()); - - @class.AppendChild(classSummary); - @class.AppendChild(className); - @class.AppendChild(methods); - classes.AppendChild(@class); + classSummary.Add(new XAttribute("numSequencePoints", cls.Value.Select(c => c.Value.Count).Sum().ToString())); + classSummary.Add(new XAttribute("visitedSequencePoints", cls.Value.Select(c => c.Value.Where(l => l.Value.Hits > 0).Count()).Sum().ToString())); + classSummary.Add(new XAttribute("numBranchPoints", cls.Value.Select(c => c.Value.Count(l => l.Value.IsBranchPoint)).Sum().ToString())); + classSummary.Add(new XAttribute("visitedBranchPoints", cls.Value.Select(c => c.Value.Where(l => l.Value.Hits > 0 && l.Value.IsBranchPoint).Count()).Sum().ToString())); + classSummary.Add(new XAttribute("sequenceCoverage", summary.CalculateLineCoverage(cls.Value).ToString())); + classSummary.Add(new XAttribute("branchCoverage", summary.CalculateBranchCoverage(cls.Value).ToString())); + classSummary.Add(new XAttribute("maxCyclomaticComplexity", "0")); + classSummary.Add(new XAttribute("minCyclomaticComplexity", "0")); + classSummary.Add(new XAttribute("visitedClasses", classVisited ? "1" : "0")); + classSummary.Add(new XAttribute("numClasses", "1")); + classSummary.Add(new XAttribute("visitedMethods", "0")); + classSummary.Add(new XAttribute("numMethods", cls.Value.Count.ToString())); + + @class.Add(classSummary); + @class.Add(className); + @class.Add(methods); + classes.Add(@class); } i++; } - module.AppendChild(files); - module.AppendChild(classes); - modules.AppendChild(module); + module.Add(files); + module.Add(classes); + modules.Add(module); } - coverageSummary.SetAttribute("numSequencePoints", numSequencePoints.ToString()); - coverageSummary.SetAttribute("visitedSequencePoints", visitedSequencePoints.ToString()); - coverageSummary.SetAttribute("numBranchPoints", numBranchPoints.ToString()); - coverageSummary.SetAttribute("visitedBranchPoints", visitedBranchPoints.ToString()); - coverageSummary.SetAttribute("sequenceCoverage", summary.CalculateLineCoverage(result.Modules).ToString()); - coverageSummary.SetAttribute("branchCoverage", summary.CalculateLineCoverage(result.Modules).ToString()); - coverageSummary.SetAttribute("maxCyclomaticComplexity", "0"); - coverageSummary.SetAttribute("minCyclomaticComplexity", "0"); - coverageSummary.SetAttribute("visitedClasses", visitedClasses.ToString()); - coverageSummary.SetAttribute("numClasses", numClasses.ToString()); - coverageSummary.SetAttribute("visitedMethods", visitedMethods.ToString()); - coverageSummary.SetAttribute("numMethods", numMethods.ToString()); - - coverage.AppendChild(coverageSummary); - coverage.AppendChild(modules); - xml.AppendChild(coverage); - - Utf8StringWriter writer = new Utf8StringWriter(); - xml.Save(writer); - - return writer.ToString(); + coverageSummary.Add(new XAttribute("numSequencePoints", numSequencePoints.ToString())); + coverageSummary.Add(new XAttribute("visitedSequencePoints", visitedSequencePoints.ToString())); + coverageSummary.Add(new XAttribute("numBranchPoints", numBranchPoints.ToString())); + coverageSummary.Add(new XAttribute("visitedBranchPoints", visitedBranchPoints.ToString())); + coverageSummary.Add(new XAttribute("sequenceCoverage", summary.CalculateLineCoverage(result.Modules).ToString())); + coverageSummary.Add(new XAttribute("branchCoverage", summary.CalculateLineCoverage(result.Modules).ToString())); + coverageSummary.Add(new XAttribute("maxCyclomaticComplexity", "0")); + coverageSummary.Add(new XAttribute("minCyclomaticComplexity", "0")); + coverageSummary.Add(new XAttribute("visitedClasses", visitedClasses.ToString())); + coverageSummary.Add(new XAttribute("numClasses", numClasses.ToString())); + coverageSummary.Add(new XAttribute("visitedMethods", visitedMethods.ToString())); + coverageSummary.Add(new XAttribute("numMethods", numMethods.ToString())); + + coverage.Add(coverageSummary); + coverage.Add(modules); + xml.Add(coverage); + + var stream = new MemoryStream(); + xml.Save(stream); + + return Encoding.UTF8.GetString(stream.GetBuffer()); } } } \ No newline at end of file From 67dcff9c66716ac01b812ce2b73de916b260db7a Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Tue, 17 Apr 2018 12:19:26 +0100 Subject: [PATCH 3/6] remove invalid characters from opencover output --- src/coverlet.core/Reporters/OpenCoverReporter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index 196efd036..9a150923e 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -16,7 +16,7 @@ public class OpenCoverReporter : IReporter public string Report(CoverageResult result) { CoverageSummary summary = new CoverageSummary(); - XDocument xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + XDocument xml = new XDocument(); XElement coverage = new XElement("CoverageSession"); XElement coverageSummary = new XElement("Summary"); XElement modules = new XElement("Modules"); @@ -219,7 +219,7 @@ public string Report(CoverageResult result) var stream = new MemoryStream(); xml.Save(stream); - return Encoding.UTF8.GetString(stream.GetBuffer()); + return Encoding.UTF8.GetString(stream.ToArray()); } } } \ No newline at end of file From b0adf7728b461de6764357d8a282585e7aa29c0a Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Tue, 17 Apr 2018 12:20:12 +0100 Subject: [PATCH 4/6] fix encoding of cobertura output --- .../Reporters/CoberturaReporter.cs | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 0454b9968..12964f94b 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Xml; +using System.Xml.Linq; namespace Coverlet.Core.Reporters { @@ -16,82 +18,81 @@ public string Report(CoverageResult result) { CoverageSummary summary = new CoverageSummary(); - XmlDocument xml = new XmlDocument(); - XmlElement coverage = xml.CreateElement("coverage"); - coverage.SetAttribute("line-rate", summary.CalculateLineCoverage(result.Modules).ToString()); - coverage.SetAttribute("branch-rate", summary.CalculateBranchCoverage(result.Modules).ToString()); - coverage.SetAttribute("version", "1.9"); - coverage.SetAttribute("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString()); + XDocument xml = new XDocument(); + XElement coverage = new XElement("coverage"); + coverage.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(result.Modules).ToString())); + coverage.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(result.Modules).ToString())); + coverage.Add(new XAttribute("version", "1.9")); + coverage.Add(new XAttribute("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString())); - XmlElement sources = xml.CreateElement("sources"); + XElement sources = new XElement("sources"); foreach (var src in GetSources(result.Modules)) { - XmlElement source = xml.CreateElement("source"); - source.AppendChild(xml.CreateTextNode(src)); - sources.AppendChild(source); + XElement source = new XElement("source", src); + sources.Add(source); } - XmlElement packages = xml.CreateElement("packages"); + XElement packages = new XElement("packages"); foreach (var module in result.Modules) { - XmlElement package = xml.CreateElement("package"); - package.SetAttribute("line-rate", summary.CalculateLineCoverage(module.Value).ToString()); - package.SetAttribute("branch-rate", summary.CalculateBranchCoverage(module.Value).ToString()); - package.SetAttribute("complexity", "0"); + XElement package = new XElement("package"); + package.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(module.Value).ToString())); + package.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(module.Value).ToString())); + package.Add(new XAttribute("complexity", "0")); - XmlElement classes = xml.CreateElement("classes"); + XElement classes = new XElement("classes"); foreach (var document in module.Value) { foreach (var cls in document.Value) { - XmlElement @class = xml.CreateElement("class"); - @class.SetAttribute("name", cls.Key); - @class.SetAttribute("filename", Path.GetFileName(document.Key)); - @class.SetAttribute("line-rate", summary.CalculateLineCoverage(cls.Value).ToString()); - @class.SetAttribute("branch-rate", summary.CalculateBranchCoverage(cls.Value).ToString()); - @class.SetAttribute("complexity", "0"); - - XmlElement methods = xml.CreateElement("methods"); + XElement @class = new XElement("class"); + @class.Add(new XAttribute("name", cls.Key)); + @class.Add(new XAttribute("filename", Path.GetFileName(document.Key))); + @class.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(cls.Value).ToString())); + @class.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(cls.Value).ToString())); + @class.Add(new XAttribute("complexity", "0")); + + XElement methods = new XElement("methods"); foreach (var meth in cls.Value) { - XmlElement method = xml.CreateElement("method"); - method.SetAttribute("name", meth.Key.Split(':')[2].Split('(')[0]); - method.SetAttribute("signature", meth.Key); - method.SetAttribute("line-rate", summary.CalculateLineCoverage(meth.Value).ToString()); - method.SetAttribute("branch-rate", summary.CalculateBranchCoverage(meth.Value).ToString()); + XElement method = new XElement("method"); + method.Add(new XAttribute("name", meth.Key.Split(':')[2].Split('(')[0])); + method.Add(new XAttribute("signature", meth.Key)); + method.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(meth.Value).ToString())); + method.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(meth.Value).ToString())); - XmlElement lines = xml.CreateElement("lines"); + XElement lines = new XElement("lines"); foreach (var ln in meth.Value) { - XmlElement line = xml.CreateElement("line"); - line.SetAttribute("number", ln.Key.ToString()); - line.SetAttribute("hits", ln.Value.Hits.ToString()); - line.SetAttribute("branch", ln.Value.IsBranchPoint.ToString()); + XElement line = new XElement("line"); + line.Add(new XAttribute("number", ln.Key.ToString())); + line.Add(new XAttribute("hits", ln.Value.Hits.ToString())); + line.Add(new XAttribute("branch", ln.Value.IsBranchPoint.ToString())); - lines.AppendChild(line); + lines.Add(line); } - method.AppendChild(lines); - methods.AppendChild(method); + method.Add(lines); + methods.Add(method); } - @class.AppendChild(methods); - classes.AppendChild(@class); + @class.Add(methods); + classes.Add(@class); } } - package.AppendChild(classes); - packages.AppendChild(package); + package.Add(classes); + packages.Add(package); } - coverage.AppendChild(sources); - coverage.AppendChild(packages); - xml.AppendChild(coverage); + coverage.Add(sources); + coverage.Add(packages); + xml.Add(coverage); - StringWriter writer = new StringWriter(); - xml.Save(writer); + var stream = new MemoryStream(); + xml.Save(stream); - return writer.ToString(); + return Encoding.UTF8.GetString(stream.ToArray()); } private string[] GetSources(Modules modules) From e2f8ebe4261468885c9094fb2fc3b95683a17e27 Mon Sep 17 00:00:00 2001 From: Toni Solarin-Sodara Date: Tue, 17 Apr 2018 14:13:32 +0100 Subject: [PATCH 5/6] fix opencover reportgenerator error --- src/coverlet.core/Reporters/OpenCoverReporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index 9a150923e..9e4fb4694 100644 --- a/src/coverlet.core/Reporters/OpenCoverReporter.cs +++ b/src/coverlet.core/Reporters/OpenCoverReporter.cs @@ -121,6 +121,9 @@ public string Report(CoverageResult result) branchPoint.Add(new XAttribute("vc", lines.Value.Hits.ToString())); branchPoint.Add(new XAttribute("upsid", lines.Key.ToString())); branchPoint.Add(new XAttribute("ordinal", kBr.ToString())); + branchPoint.Add(new XAttribute("path", "")); + branchPoint.Add(new XAttribute("offset", kBr.ToString())); + branchPoint.Add(new XAttribute("offsetend", kBr.ToString())); branchPoint.Add(new XAttribute("sl", lines.Key.ToString())); branchPoint.Add(new XAttribute("fileid", i.ToString())); branchPoints.Add(branchPoint); From fb5f20fc571f82a0449c7f8be624721fa83a1fe3 Mon Sep 17 00:00:00 2001 From: Toni Solarin-Sodara Date: Tue, 17 Apr 2018 23:04:15 +0100 Subject: [PATCH 6/6] fix cobertura report generator output --- .../Reporters/CoberturaReporter.cs | 65 ++++++++++++++++--- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 12964f94b..79ab28b3c 100644 --- a/src/coverlet.core/Reporters/CoberturaReporter.cs +++ b/src/coverlet.core/Reporters/CoberturaReporter.cs @@ -18,6 +18,8 @@ public string Report(CoverageResult result) { CoverageSummary summary = new CoverageSummary(); + int totalLines = 0, coveredLines = 0, totalBranches = 0, coveredBranches = 0; + XDocument xml = new XDocument(); XElement coverage = new XElement("coverage"); coverage.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(result.Modules).ToString())); @@ -26,16 +28,14 @@ public string Report(CoverageResult result) coverage.Add(new XAttribute("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString())); XElement sources = new XElement("sources"); - foreach (var src in GetSources(result.Modules)) - { - XElement source = new XElement("source", src); - sources.Add(source); - } + var basePath = GetBasePath(result.Modules); + sources.Add(new XElement("source", basePath)); XElement packages = new XElement("packages"); foreach (var module in result.Modules) { XElement package = new XElement("package"); + package.Add(new XAttribute("name", Path.GetFileNameWithoutExtension(module.Key))); package.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(module.Value).ToString())); package.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(module.Value).ToString())); package.Add(new XAttribute("complexity", "0")); @@ -47,17 +47,19 @@ public string Report(CoverageResult result) { XElement @class = new XElement("class"); @class.Add(new XAttribute("name", cls.Key)); - @class.Add(new XAttribute("filename", Path.GetFileName(document.Key))); + @class.Add(new XAttribute("filename", GetRelativePathFromBase(basePath, document.Key))); @class.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(cls.Value).ToString())); @class.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(cls.Value).ToString())); @class.Add(new XAttribute("complexity", "0")); + XElement classLines = new XElement("lines"); XElement methods = new XElement("methods"); + foreach (var meth in cls.Value) { XElement method = new XElement("method"); method.Add(new XAttribute("name", meth.Key.Split(':')[2].Split('(')[0])); - method.Add(new XAttribute("signature", meth.Key)); + method.Add(new XAttribute("signature", "(" + meth.Key.Split(':')[2].Split('(')[1])); method.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(meth.Value).ToString())); method.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(meth.Value).ToString())); @@ -69,7 +71,29 @@ public string Report(CoverageResult result) line.Add(new XAttribute("hits", ln.Value.Hits.ToString())); line.Add(new XAttribute("branch", ln.Value.IsBranchPoint.ToString())); + totalLines++; + if (ln.Value.Hits > 0) coveredLines++; + + + if (ln.Value.IsBranchPoint) + { + line.Add(new XAttribute("condition-coverage", "100% (1/1)")); + XElement conditions = new XElement("conditions"); + XElement condition = new XElement("condition"); + condition.Add(new XAttribute("number", "0")); + condition.Add(new XAttribute("type", "jump")); + condition.Add(new XAttribute("coverage", "100%")); + + totalBranches++; + if (ln.Value.Hits > 0) coveredBranches++; + + conditions.Add(condition); + line.Add(conditions); + } + + lines.Add(line); + classLines.Add(line); } method.Add(lines); @@ -77,6 +101,7 @@ public string Report(CoverageResult result) } @class.Add(methods); + @class.Add(classLines); classes.Add(@class); } } @@ -85,6 +110,11 @@ public string Report(CoverageResult result) packages.Add(package); } + coverage.Add(new XAttribute("lines-covered", coveredLines.ToString())); + coverage.Add(new XAttribute("lines-valid", totalLines.ToString())); + coverage.Add(new XAttribute("branches-covered", coveredBranches.ToString())); + coverage.Add(new XAttribute("branches-valid", totalBranches.ToString())); + coverage.Add(sources); coverage.Add(packages); xml.Add(coverage); @@ -95,16 +125,33 @@ public string Report(CoverageResult result) return Encoding.UTF8.GetString(stream.ToArray()); } - private string[] GetSources(Modules modules) + private string GetBasePath(Modules modules) { List sources = new List(); + string source = string.Empty; + foreach (var module in modules) { sources.AddRange( module.Value.Select(d => Path.GetDirectoryName(d.Key))); } - return sources.Distinct().ToArray(); + sources = sources.Distinct().ToList(); + var segments = sources[0].Split(Path.DirectorySeparatorChar); + + foreach (var segment in segments) + { + var startsWith = sources.All(s => s.StartsWith(source + segment)); + if (!startsWith) + break; + + source += segment + Path.DirectorySeparatorChar; + } + + return source; } + + private string GetRelativePathFromBase(string source, string path) + => path.Replace(source, string.Empty); } } \ No newline at end of file