Skip to content

Commit 1ade053

Browse files
authored
Merge pull request #50 from tonerdo/output-format-fixes
Fix Coverlet output formats
2 parents 84e18a2 + fb5f20f commit 1ade053

File tree

4 files changed

+247
-203
lines changed

4 files changed

+247
-203
lines changed

src/coverlet.core/Reporters/CoberturaReporter.cs

Lines changed: 100 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using System.Text;
56
using System.Xml;
7+
using System.Xml.Linq;
68

79
namespace Coverlet.Core.Reporters
810
{
@@ -16,94 +18,140 @@ public string Report(CoverageResult result)
1618
{
1719
CoverageSummary summary = new CoverageSummary();
1820

19-
XmlDocument xml = new XmlDocument();
20-
XmlElement coverage = xml.CreateElement("coverage");
21-
coverage.SetAttribute("line-rate", summary.CalculateLineCoverage(result.Modules).ToString());
22-
coverage.SetAttribute("branch-rate", summary.CalculateBranchCoverage(result.Modules).ToString());
23-
coverage.SetAttribute("version", "1.9");
24-
coverage.SetAttribute("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString());
21+
int totalLines = 0, coveredLines = 0, totalBranches = 0, coveredBranches = 0;
2522

26-
XmlElement sources = xml.CreateElement("sources");
27-
foreach (var src in GetSources(result.Modules))
28-
{
29-
XmlElement source = xml.CreateElement("source");
30-
source.AppendChild(xml.CreateTextNode(src));
31-
sources.AppendChild(source);
32-
}
23+
XDocument xml = new XDocument();
24+
XElement coverage = new XElement("coverage");
25+
coverage.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(result.Modules).ToString()));
26+
coverage.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(result.Modules).ToString()));
27+
coverage.Add(new XAttribute("version", "1.9"));
28+
coverage.Add(new XAttribute("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString()));
29+
30+
XElement sources = new XElement("sources");
31+
var basePath = GetBasePath(result.Modules);
32+
sources.Add(new XElement("source", basePath));
3333

34-
XmlElement packages = xml.CreateElement("packages");
34+
XElement packages = new XElement("packages");
3535
foreach (var module in result.Modules)
3636
{
37-
XmlElement package = xml.CreateElement("package");
38-
package.SetAttribute("line-rate", summary.CalculateLineCoverage(module.Value).ToString());
39-
package.SetAttribute("branch-rate", summary.CalculateBranchCoverage(module.Value).ToString());
40-
package.SetAttribute("complexity", "0");
37+
XElement package = new XElement("package");
38+
package.Add(new XAttribute("name", Path.GetFileNameWithoutExtension(module.Key)));
39+
package.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(module.Value).ToString()));
40+
package.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(module.Value).ToString()));
41+
package.Add(new XAttribute("complexity", "0"));
4142

42-
XmlElement classes = xml.CreateElement("classes");
43+
XElement classes = new XElement("classes");
4344
foreach (var document in module.Value)
4445
{
4546
foreach (var cls in document.Value)
4647
{
47-
XmlElement @class = xml.CreateElement("class");
48-
@class.SetAttribute("name", cls.Key);
49-
@class.SetAttribute("filename", Path.GetFileName(document.Key));
50-
@class.SetAttribute("line-rate", summary.CalculateLineCoverage(cls.Value).ToString());
51-
@class.SetAttribute("branch-rate", summary.CalculateBranchCoverage(cls.Value).ToString());
52-
@class.SetAttribute("complexity", "0");
53-
54-
XmlElement methods = xml.CreateElement("methods");
48+
XElement @class = new XElement("class");
49+
@class.Add(new XAttribute("name", cls.Key));
50+
@class.Add(new XAttribute("filename", GetRelativePathFromBase(basePath, document.Key)));
51+
@class.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(cls.Value).ToString()));
52+
@class.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(cls.Value).ToString()));
53+
@class.Add(new XAttribute("complexity", "0"));
54+
55+
XElement classLines = new XElement("lines");
56+
XElement methods = new XElement("methods");
57+
5558
foreach (var meth in cls.Value)
5659
{
57-
XmlElement method = xml.CreateElement("method");
58-
method.SetAttribute("name", meth.Key.Split(':')[2].Split('(')[0]);
59-
method.SetAttribute("signature", meth.Key);
60-
method.SetAttribute("line-rate", summary.CalculateLineCoverage(meth.Value).ToString());
61-
method.SetAttribute("branch-rate", summary.CalculateBranchCoverage(meth.Value).ToString());
60+
XElement method = new XElement("method");
61+
method.Add(new XAttribute("name", meth.Key.Split(':')[2].Split('(')[0]));
62+
method.Add(new XAttribute("signature", "(" + meth.Key.Split(':')[2].Split('(')[1]));
63+
method.Add(new XAttribute("line-rate", summary.CalculateLineCoverage(meth.Value).ToString()));
64+
method.Add(new XAttribute("branch-rate", summary.CalculateBranchCoverage(meth.Value).ToString()));
6265

63-
XmlElement lines = xml.CreateElement("lines");
66+
XElement lines = new XElement("lines");
6467
foreach (var ln in meth.Value)
6568
{
66-
XmlElement line = xml.CreateElement("line");
67-
line.SetAttribute("number", ln.Key.ToString());
68-
line.SetAttribute("hits", ln.Value.Hits.ToString());
69-
line.SetAttribute("branch", ln.Value.IsBranchPoint.ToString());
69+
XElement line = new XElement("line");
70+
line.Add(new XAttribute("number", ln.Key.ToString()));
71+
line.Add(new XAttribute("hits", ln.Value.Hits.ToString()));
72+
line.Add(new XAttribute("branch", ln.Value.IsBranchPoint.ToString()));
73+
74+
totalLines++;
75+
if (ln.Value.Hits > 0) coveredLines++;
76+
77+
78+
if (ln.Value.IsBranchPoint)
79+
{
80+
line.Add(new XAttribute("condition-coverage", "100% (1/1)"));
81+
XElement conditions = new XElement("conditions");
82+
XElement condition = new XElement("condition");
83+
condition.Add(new XAttribute("number", "0"));
84+
condition.Add(new XAttribute("type", "jump"));
85+
condition.Add(new XAttribute("coverage", "100%"));
86+
87+
totalBranches++;
88+
if (ln.Value.Hits > 0) coveredBranches++;
89+
90+
conditions.Add(condition);
91+
line.Add(conditions);
92+
}
7093

71-
lines.AppendChild(line);
94+
95+
lines.Add(line);
96+
classLines.Add(line);
7297
}
7398

74-
method.AppendChild(lines);
75-
methods.AppendChild(method);
99+
method.Add(lines);
100+
methods.Add(method);
76101
}
77102

78-
@class.AppendChild(methods);
79-
classes.AppendChild(@class);
103+
@class.Add(methods);
104+
@class.Add(classLines);
105+
classes.Add(@class);
80106
}
81107
}
82108

83-
package.AppendChild(classes);
84-
packages.AppendChild(package);
109+
package.Add(classes);
110+
packages.Add(package);
85111
}
86112

87-
coverage.AppendChild(sources);
88-
coverage.AppendChild(packages);
89-
xml.AppendChild(coverage);
113+
coverage.Add(new XAttribute("lines-covered", coveredLines.ToString()));
114+
coverage.Add(new XAttribute("lines-valid", totalLines.ToString()));
115+
coverage.Add(new XAttribute("branches-covered", coveredBranches.ToString()));
116+
coverage.Add(new XAttribute("branches-valid", totalBranches.ToString()));
117+
118+
coverage.Add(sources);
119+
coverage.Add(packages);
120+
xml.Add(coverage);
90121

91-
StringWriter writer = new StringWriter();
92-
xml.Save(writer);
122+
var stream = new MemoryStream();
123+
xml.Save(stream);
93124

94-
return writer.ToString();
125+
return Encoding.UTF8.GetString(stream.ToArray());
95126
}
96127

97-
private string[] GetSources(Modules modules)
128+
private string GetBasePath(Modules modules)
98129
{
99130
List<string> sources = new List<string>();
131+
string source = string.Empty;
132+
100133
foreach (var module in modules)
101134
{
102135
sources.AddRange(
103136
module.Value.Select(d => Path.GetDirectoryName(d.Key)));
104137
}
105138

106-
return sources.Distinct().ToArray();
139+
sources = sources.Distinct().ToList();
140+
var segments = sources[0].Split(Path.DirectorySeparatorChar);
141+
142+
foreach (var segment in segments)
143+
{
144+
var startsWith = sources.All(s => s.StartsWith(source + segment));
145+
if (!startsWith)
146+
break;
147+
148+
source += segment + Path.DirectorySeparatorChar;
149+
}
150+
151+
return source;
107152
}
153+
154+
private string GetRelativePathFromBase(string source, string path)
155+
=> path.Replace(source, string.Empty);
108156
}
109157
}

src/coverlet.core/Reporters/LcovReporter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public string Report(CoverageResult result)
2323
{
2424
foreach (var line in method.Value)
2525
{
26-
lcov.Add($"DA:{line.Key},{line.Value}");
26+
lcov.Add($"DA:{line.Key},{line.Value.Hits}");
2727
}
2828
}
2929
}

0 commit comments

Comments
 (0)