diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs index 0454b9968..79ab28b3c 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,94 +18,140 @@ 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()); + int totalLines = 0, coveredLines = 0, totalBranches = 0, coveredBranches = 0; - XmlElement sources = xml.CreateElement("sources"); - foreach (var src in GetSources(result.Modules)) - { - XmlElement source = xml.CreateElement("source"); - source.AppendChild(xml.CreateTextNode(src)); - sources.AppendChild(source); - } + 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())); + + XElement sources = new XElement("sources"); + var basePath = GetBasePath(result.Modules); + sources.Add(new XElement("source", basePath)); - 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("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")); - 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", 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) { - 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.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())); - 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())); + + 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.AppendChild(line); + + lines.Add(line); + classLines.Add(line); } - method.AppendChild(lines); - methods.AppendChild(method); + method.Add(lines); + methods.Add(method); } - @class.AppendChild(methods); - classes.AppendChild(@class); + @class.Add(methods); + @class.Add(classLines); + 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(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); - 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) + 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 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/src/coverlet.core/Reporters/OpenCoverReporter.cs b/src/coverlet.core/Reporters/OpenCoverReporter.cs index f2f7e5c27..9e4fb4694 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(); + 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,105 @@ 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("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); kBr++; numBranchPoints++; } @@ -158,27 +148,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 +176,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.ToArray()); } } } \ No newline at end of file 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