Branch coverage differs between OpenCover and Cobertura
See original GitHub issueGiven the following class being tested and a test of the ConditionalOperator method.
The report generator gives different branch coverage for a report generated from a Cobertura file from Coverlet ( .Net Core version of files below ) to a report generated from an OpenCover file file from OpenCover ( .Net Framework version of the files below ).
public class ToTest
{
public string ConditionalOperator(bool isTrue)
{
return isTrue ? "True" : "False";
}
}
public class UnitTest1
{
[Fact]
public void Test1()
{
var toTest = new ToTest();
toTest.ConditionalOperator(true);
}
}
66.7% for Net Framework OpenCover , 50% for .NetCore Coverlet
C:\Users\tonyh\AppData\Local\FineCodeCoverage\reportGenerator>reportgenerator -targetdir:C:\Users\tonyh\Downloads\reporter_output -reports:C:\Users\tonyh\Source\Repos\SUT\Test\bin\Debug\netcoreapp3.1\fine-code-coverage\project.coverage.xml;C:\Users\tonyh\Source\Repos\SUT\UnitTestNetFramework\bin\Debug\fine-code-coverage\project.coverage.xml
2020-12-28T16:17:43: Arguments
2020-12-28T16:17:43: -targetdir:C:\Users\tonyh\Downloads\reporter_output
2020-12-28T16:17:43: -reports:C:\Users\tonyh\Source\Repos\SUT\Test\bin\Debug\netcoreapp3.1\fine-code-coverage\project.coverage.xml;C:\Users\tonyh\Source\Repos\SUT\UnitTestNetFramework\bin\Debug\fine-code-coverage\project.coverage.xml
2020-12-28T16:17:43: Writing report file 'C:\Users\tonyh\Downloads\reporter_output\index.html'
2020-12-28T16:17:43: Report generation took 0.3 seconds
Cobertura
<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="0.5" version="1.9" timestamp="1609172247" lines-covered="3" lines-valid="3" branches-covered="1" branches-valid="2">
<sources>
<source>C:\</source>
</sources>
<packages>
<package name="SUT" line-rate="1" branch-rate="0.5" complexity="2">
<classes>
<class name="SUT.ToTest" filename="Users\tonyh\Source\Repos\SUT\SUT\ToTest.cs" line-rate="1" branch-rate="0.5" complexity="2">
<methods>
<method name="ConditionalOperator" signature="(System.Boolean)" line-rate="1" branch-rate="0.5" complexity="2">
<lines>
<line number="28" hits="1" branch="False" />
<line number="29" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="2" type="jump" coverage="50%" />
</conditions>
</line>
<line number="30" hits="1" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="28" hits="1" branch="False" />
<line number="29" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="2" type="jump" coverage="50%" />
</conditions>
</line>
<line number="30" hits="1" branch="False" />
</lines>
</class>
</classes>
</package>
</packages>
</coverage>
OpenCover
<?xml version="1.0" encoding="utf-8"?>
<CoverageSession xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="4.7.922.0">
<Summary numSequencePoints="3" visitedSequencePoints="3" numBranchPoints="3" visitedBranchPoints="2" sequenceCoverage="100" branchCoverage="66.67" maxCyclomaticComplexity="3" minCyclomaticComplexity="1" maxCrapScore="3" minCrapScore="2" visitedClasses="1" numClasses="1" visitedMethods="1" numMethods="1" />
<Modules>
<Module hash="5B-E7-52-BD-E0-D0-91-41-A2-A5-8E-5E-07-FD-C6-38-75-C8-9E-69">
<Summary numSequencePoints="3" visitedSequencePoints="3" numBranchPoints="3" visitedBranchPoints="2" sequenceCoverage="100" branchCoverage="66.67" maxCyclomaticComplexity="3" minCyclomaticComplexity="1" maxCrapScore="3" minCrapScore="2" visitedClasses="1" numClasses="1" visitedMethods="1" numMethods="1" />
<ModulePath>C:\Users\tonyh\Source\Repos\SUT\UnitTestNetFramework\bin\Debug\SUTNetFramework.dll</ModulePath>
<ModuleTime>2020-12-28T16:16:17.9590077Z</ModuleTime>
<ModuleName>SUTNetFramework</ModuleName>
<Files>
<File uid="1" fullPath="C:\Users\tonyh\Source\Repos\SUT\SUTNetFramework\Class1.cs" />
</Files>
<Classes>
<Class>
<Summary numSequencePoints="3" visitedSequencePoints="3" numBranchPoints="3" visitedBranchPoints="2" sequenceCoverage="100" branchCoverage="66.67" maxCyclomaticComplexity="3" minCyclomaticComplexity="1" maxCrapScore="3" minCrapScore="2" visitedClasses="1" numClasses="1" visitedMethods="1" numMethods="1" />
<FullName>SUTNetFramework.ToTest</FullName>
<Methods>
<Method visited="true" cyclomaticComplexity="3" nPathComplexity="2" sequenceCoverage="100" branchCoverage="66.67" crapScore="3" isConstructor="false" isStatic="false" isGetter="false" isSetter="false">
<Summary numSequencePoints="3" visitedSequencePoints="3" numBranchPoints="3" visitedBranchPoints="2" sequenceCoverage="100" branchCoverage="66.67" maxCyclomaticComplexity="3" minCyclomaticComplexity="3" maxCrapScore="3" minCrapScore="3" visitedClasses="0" numClasses="0" visitedMethods="1" numMethods="1" />
<MetadataToken>100663297</MetadataToken>
<Name>System.String SUTNetFramework.ToTest::ConditionalOperator(System.Boolean)</Name>
<FileRef uid="1" />
<SequencePoints>
<SequencePoint vc="1" uspid="1" ordinal="0" offset="0" sl="32" sc="9" el="32" ec="10" bec="0" bev="0" fileid="1" />
<SequencePoint vc="1" uspid="2" ordinal="1" offset="1" sl="33" sc="13" el="33" ec="46" bec="2" bev="1" fileid="1" />
<SequencePoint vc="1" uspid="3" ordinal="2" offset="19" sl="34" sc="9" el="34" ec="10" bec="0" bev="0" fileid="1" />
</SequencePoints>
<BranchPoints>
<BranchPoint vc="0" uspid="4" ordinal="0" offset="2" sl="33" path="0" offsetend="4" fileid="1" />
<BranchPoint vc="1" uspid="5" ordinal="1" offset="2" sl="33" path="1" offsetend="11" fileid="1" />
</BranchPoints>
<MethodPoint xsi:type="SequencePoint" vc="1" uspid="1" ordinal="0" offset="0" sl="32" sc="9" el="32" ec="10" bec="0" bev="0" fileid="1" />
</Method>
<Method visited="false" cyclomaticComplexity="1" nPathComplexity="0" sequenceCoverage="0" branchCoverage="0" crapScore="2" isConstructor="true" isStatic="false" isGetter="false" isSetter="false">
<Summary numSequencePoints="0" visitedSequencePoints="0" numBranchPoints="0" visitedBranchPoints="0" sequenceCoverage="0" branchCoverage="0" maxCyclomaticComplexity="1" minCyclomaticComplexity="1" maxCrapScore="2" minCrapScore="2" visitedClasses="0" numClasses="0" visitedMethods="0" numMethods="0" />
<MetadataToken>100663298</MetadataToken>
<Name>System.Void SUTNetFramework.ToTest::.ctor()</Name>
<SequencePoints />
<BranchPoints />
<MethodPoint vc="0" uspid="6" ordinal="0" offset="0" />
</Method>
</Methods>
</Class>
</Classes>
</Module>
</Modules>
</CoverageSession>
Despite OpenCover reporting
numBranchPoints="3" visitedBranchPoints="2"
From https://github.com/danielpalme/ReportGenerator/issues/321#issuecomment-584333807
Only “real” branches ( in OpenCover XML) are taken into account. OpenCover counts differently here, it counts one extra branch per method.
I expect the percentage to be the same for the two report types.
Issue Analytics
- State:
- Created 3 years ago
- Comments:8 (3 by maintainers)

Top Related StackOverflow Question
The calculation-details page does not have a visible link on the wiki home page https://github.com/danielpalme/ReportGenerator/wiki
It is there in the collapsed pages section
All metrics are not 100% accurate if you merge several coverage files. Therefore I decided to show them “as is”. Otherwise I would have to recalculate all of them (which is often not possible without analyzing the source code).