Skip to content

Commit

Permalink
Add mini opencoverage xml report support
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosrodcam committed Feb 25, 2018
1 parent 05ab17b commit 83851e7
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $MiniCover uninstrument
$MiniCover htmlreport --threshold 90
$MiniCover xmlreport --threshold 90
$MiniCover report --threshold 90
$MiniCover opencoverreport --threshold 90 --output opencovercoverage.xml

if [ "${TRAVIS_PULL_REQUEST}" = "false" ] && [ "${TRAVIS_BRANCH}" = "master" ]; then
dotnet pack src/MiniCover -c Release --output $PWD/artifacts --version-suffix ci-`date +%Y%m%d%H%M%S`
Expand Down
90 changes: 90 additions & 0 deletions opencovercoverage.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?xml-stylesheet type='text/xsl' href='coverage.xsl'?>
<CoverageSession>
<Module hash="846bdfa0-e24a-4dd7-9d6e-3e55c3cf0712">
<FullName>MiniCover.Tests</FullName>
<ModuleName>MiniCover.Tests</ModuleName>
<File uid="1" fullPath="/home/carlos/micover/minicover/test/MiniCover.Tests/AnotherClass.cs" />
<Class>
<FullName>MiniCover.Tests.AnotherClass</FullName>
<Method visited="true" isConstructor="false">
<Name>System.Int32 MiniCover.Tests.AnotherClass::get_SomeProperty()</Name>
<FileRef uid="1" />
<SequencePoint vc="1" uspid="1" ordinal="1" sl="11" sc="17" el="11" ec="38" />
</Method>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.Tests.AnotherClass::set_SomeProperty(System.Int32)</Name>
<FileRef uid="1" />
<SequencePoint vc="1" uspid="2" ordinal="1" sl="15" sc="17" el="15" ec="39" />
</Method>
<Method visited="true" isConstructor="false">
<Name>System.Int32 MiniCover.Tests.AnotherClass::SomeMethod()</Name>
<FileRef uid="1" />
<SequencePoint vc="1" uspid="3" ordinal="1" sl="21" sc="13" el="21" ec="37" />
</Method>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.Tests.AnotherClass::AnotherMethod()</Name>
<FileRef uid="1" />
<SequencePoint vc="1" uspid="4" ordinal="1" sl="26" sc="13" el="26" ec="45" />
</Method>
<Method visited="true" isConstructor="true">
<Name>System.Void MiniCover.Tests.AnotherClass::.ctor()</Name>
<FileRef uid="1" />
<SequencePoint vc="1" uspid="5" ordinal="1" sl="5" sc="9" el="5" ec="39" />
</Method>
</Class>
</Module>
<Module hash="14e70cce-128b-447e-83bc-5df494b828b3">
<FullName>MiniCover.XUnit.Tests</FullName>
<ModuleName>MiniCover.XUnit.Tests</ModuleName>
<File uid="2" fullPath="/home/carlos/micover/minicover/test/MiniCover.XUnit.Tests/UnitTest1.cs" />
<Class>
<FullName>MiniCover.XUnit.Tests.UnitTest1</FullName>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.XUnit.Tests.UnitTest1::XUnitTest1()</Name>
<FileRef uid="2" />
<SequencePoint vc="1" uspid="6" ordinal="1" sl="11" sc="13" el="11" ec="23" />
<SequencePoint vc="1" uspid="7" ordinal="2" sl="12" sc="13" el="12" ec="23" />
<SequencePoint vc="1" uspid="8" ordinal="3" sl="13" sc="13" el="13" ec="27" />
<SequencePoint vc="1" uspid="9" ordinal="4" sl="15" sc="13" el="15" ec="32" />
<SequencePoint vc="1" uspid="10" ordinal="5" sl="16" sc="13" el="16" ec="32" />
<SequencePoint vc="1" uspid="11" ordinal="6" sl="18" sc="13" el="18" ec="45" />
</Method>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.XUnit.Tests.UnitTest1::XUnitTest2()</Name>
<FileRef uid="2" />
<SequencePoint vc="1" uspid="12" ordinal="1" sl="24" sc="13" el="24" ec="23" />
<SequencePoint vc="1" uspid="13" ordinal="2" sl="25" sc="13" el="25" ec="23" />
<SequencePoint vc="1" uspid="14" ordinal="3" sl="27" sc="13" el="27" ec="24" />
<SequencePoint vc="0" uspid="15" ordinal="4" sl="29" sc="17" el="29" ec="36" />
<SequencePoint vc="1" uspid="16" ordinal="5" sl="32" sc="13" el="32" ec="48" />
</Method>
</Class>
</Module>
<Module hash="6a8354f1-0cdb-4de0-ac8b-08040cc1be9a">
<FullName>MiniCover.NUnit.Tests</FullName>
<ModuleName>MiniCover.NUnit.Tests</ModuleName>
<File uid="3" fullPath="/home/carlos/micover/minicover/test/MiniCover.NUnit.Tests/UnitTest1.cs" />
<Class>
<FullName>MiniCover.NUnit.Tests.UnitTest1</FullName>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.NUnit.Tests.UnitTest1::NUnitTest1()</Name>
<FileRef uid="3" />
<SequencePoint vc="1" uspid="17" ordinal="1" sl="12" sc="13" el="12" ec="23" />
<SequencePoint vc="1" uspid="18" ordinal="2" sl="13" sc="13" el="13" ec="23" />
<SequencePoint vc="1" uspid="19" ordinal="3" sl="14" sc="13" el="14" ec="27" />
<SequencePoint vc="1" uspid="20" ordinal="4" sl="16" sc="13" el="16" ec="35" />
<SequencePoint vc="1" uspid="21" ordinal="5" sl="17" sc="13" el="17" ec="35" />
<SequencePoint vc="1" uspid="22" ordinal="6" sl="19" sc="13" el="19" ec="45" />
</Method>
<Method visited="true" isConstructor="false">
<Name>System.Void MiniCover.NUnit.Tests.UnitTest1::NUnitTest2()</Name>
<FileRef uid="3" />
<SequencePoint vc="1" uspid="23" ordinal="1" sl="25" sc="13" el="25" ec="23" />
<SequencePoint vc="1" uspid="24" ordinal="2" sl="26" sc="13" el="26" ec="23" />
<SequencePoint vc="1" uspid="25" ordinal="3" sl="28" sc="13" el="28" ec="24" />
<SequencePoint vc="0" uspid="26" ordinal="4" sl="30" sc="17" el="30" ec="39" />
<SequencePoint vc="1" uspid="27" ordinal="5" sl="33" sc="13" el="33" ec="48" />
</Method>
</Class>
</Module>
</CoverageSession>
23 changes: 23 additions & 0 deletions src/MiniCover/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,29 @@ static int Main(string[] args)
});
});

commandLineApplication.Command("opencoverreport", command =>
{
command.Description = "Write an OpenCover-formatted XML report to folder";

var workDirOption = CreateWorkdirOption(command);
var coverageFileOption = CreateCoverageFileOption(command);
var thresholdOption = CreateThresholdOption(command);
var outputOption = command.Option("--output", "Output file for OpenCover report [default: coverage.xml]", CommandOptionType.SingleValue);
command.HelpOption("-h | --help");

command.OnExecute(() =>
{
UpdateWorkingDirectory(workDirOption);

var coverageFile = GetCoverageFile(coverageFileOption);
var threshold = GetThreshold(thresholdOption);
var result = LoadCoverageFile(coverageFile);
var output = GetXmlReportOutput(outputOption);
OpenCoverReport.Execute(result, output, threshold);
return 0;
});
});

commandLineApplication.Command("reset", command =>
{
command.Description = "Reset hits count";
Expand Down
147 changes: 147 additions & 0 deletions src/MiniCover/Reports/OpenCoverReport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using MiniCover.Model;

namespace MiniCover.Reports
{
public static class OpenCoverReport
{
public static void Execute(InstrumentationResult result, string output, float threshold)
{
var hits = File.Exists(result.HitsFile)
? File.ReadAllLines(result.HitsFile).Select(h => int.Parse(h)).ToArray()
: new int[0];
int fileIndex = 0;
int sequencePointMegaCounter = 0;

var data = new XProcessingInstruction("xml-stylesheet", "type='text/xsl' href='coverage.xsl'");

var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), data);

var coverageElement = new XElement(
XName.Get("CoverageSession")
);

var modulesListElement = result.Assemblies.Select(assembly =>
{
var moduleElement = new XElement(
XName.Get("Module"),
new XAttribute(XName.Get("hash"), Guid.NewGuid().ToString())
);

var fullNameElement = new XElement(
XName.Get("FullName"),
new XText(assembly.Name)
);

var moduleNameElement = new XElement(
XName.Get("ModuleName"),
new XText(assembly.Name)
);

Dictionary<SourceFile, int> dctSourceFileCount = new Dictionary<SourceFile, int>();

var filesElement = assembly.SourceFiles.Select(file =>
{
dctSourceFileCount.Add(file.Value, ++fileIndex);
var fileElement = new XElement(
XName.Get("File"),
new XAttribute(XName.Get("uid"), dctSourceFileCount[file.Value]),
new XAttribute(XName.Get("fullPath"), Path.Combine(result.SourcePath, file.Key))
);

return fileElement;
});

var classesElement = assembly.SourceFiles.Select(file =>
{
var hitInstructions = file.Value.Instructions.Where(h => hits.Contains(h.Id)).ToArray();

return file.Value.Instructions
.GroupBy(instruction => new { instruction.Class })
.Select(classes =>
{
var classElement = new XElement(
XName.Get("Class")
);

var classfullNameElement = new XElement(
XName.Get("FullName"),
new XText(classes.Key.Class)
);

var methodsList = classes
.GroupBy(instruction => new { instruction.Method, instruction.MethodFullName })
.Select(method =>
{
var nameElement = new XElement(
XName.Get("Name"),
new XText(method.Key.MethodFullName)
);

var fileRefElement = new XElement(
XName.Get("FileRef"),
new XAttribute(XName.Get("uid"), dctSourceFileCount[file.Value])
);

int sequencePointMiniCounter = 0;
bool allLinesAreVisited = true;

var sequencePoints = method.Select(methodPoint =>
{
var hitCount = hitInstructions.Count(hit => hit.Equals(methodPoint));

if (hitCount == 0)
allLinesAreVisited = false;

return new XElement(
XName.Get("SequencePoint"),
new XAttribute(XName.Get("vc"), hitCount),
new XAttribute(XName.Get("uspid"), ++sequencePointMegaCounter),
new XAttribute(XName.Get("ordinal"), ++sequencePointMiniCounter),
new XAttribute(XName.Get("sl"), methodPoint.StartLine),
new XAttribute(XName.Get("sc"), methodPoint.StartColumn),
new XAttribute(XName.Get("el"), methodPoint.EndLine),
new XAttribute(XName.Get("ec"), methodPoint.EndColumn)
);
});

var methodElement = new XElement(
XName.Get("Method"),
new XAttribute(XName.Get("visited"), allLinesAreVisited),
new XAttribute(XName.Get("isConstructor"), method.Key.Method == ".ctor")
);

methodElement.Add(nameElement);
methodElement.Add(fileRefElement);
methodElement.Add(sequencePoints);

return methodElement;
});

classElement.Add(classfullNameElement);
classElement.Add(methodsList);

return classElement;
});
});

moduleElement.Add(fullNameElement);
moduleElement.Add(moduleNameElement);
moduleElement.Add(filesElement);
moduleElement.Add(classesElement);

return moduleElement;
});

coverageElement.Add(modulesListElement);

document.Add(coverageElement);

File.WriteAllText(output, document.ToString());
}
}
}

0 comments on commit 83851e7

Please sign in to comment.