Open viceice opened 8 months ago
It is also worth to mention that in the same report other lines are correctly marked, e.g.:
<line number="84" hits="1" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
</conditions>
</line>
@viceice could you please upgrade all your test projects to use latest Microsoft.NET.Test.Sdk
and Microsoft.CodeCoverage
. What commands you use to generate reports?
@viceice could you please upgrade all your test projects to use latest
Microsoft.NET.Test.Sdk
andMicrosoft.CodeCoverage
.
@jakubch1 I'm using the latest non-preview (17.9.0) of Microsoft.NET.Test.Sdk
which has a direct dependency to Microsoft.CodeCoverage
v17.9.0.
I'm using lockfiles and central versioning, so versions are verified. Should i try the latest preview?
What commands you use to generate reports?
I'm using a runsettings
file:
<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
<RunConfiguration>
<TargetPlatform>x64</TargetPlatform>
</RunConfiguration>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0">
<Configuration>
<Format>Cobertura</Format>
<CodeCoverage>
<ModulePaths>
<!-- Disable native instrumentation, causes SharePoint debug issues -->
<EnableStaticNativeInstrumentation>False</EnableStaticNativeInstrumentation>
<EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>
<Include>
<ModulePath>Proj(\.[.a-zA-Z]+)?\.dll$</ModulePath>
</Include>
<Exclude>
<ModulePath>Proj(\..+)?\.Test\.dll$</ModulePath>
</Exclude>
</ModulePaths>
<Attributes>
<Exclude>
<Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
<Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
</Exclude>
</Attributes>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
<NUnit>
<TestOutputXml>nunit</TestOutputXml>
<OutputXmlFolderMode>RelativeToResultDirectory</OutputXmlFolderMode>
<NewOutputXmlFileForEachRun>true</NewOutputXmlFileForEachRun>
</NUnit>
</RunSettings>
which is referenced in repo root Directory.Build.props
like this:
<RunSettingsFilePath>$(MSBuildThisFileDirectory)/proj.runsettings</RunSettingsFilePath>
@viceice thanks for info. How you execute tests? dotnet test
on solution level? Could you please post output of those operations?
I'm running two comands on CI.
First running cheap tests in ./test
folder on a general jenkins node inside a docker windows 2022 container. There is a sln and some test projects.
dotnet test test --no-build
...
Passed! - Failed: 0, Passed: 680, Skipped: 14, Total: 694, Duration: 17 s - Proj.Test.dll (net8.0)
Attachments:
~\proj\test\Proj.XY.Test\TestResults\c64ddcc7-72a7-45a8-aae4-32e5cafbb395\user_PCNAME_2024-02-29.08_36_39.cobertura.xml
This gives the first coverage file.
The second command runs on a native SharePoint server for CI (jenkins node) purposes. So we only run SharePoint tests here. There is a sln and one test projects.
dotnet test sp/test --no-build
...
Passed! - Failed: 0, Passed: 680, Skipped: 14, Total: 694, Duration: 17 s - Proj.SP.Test.dll (net48)
Attachments:
~\proj\sp\test\Proj.SP.Test\TestResults\5f49f3d0-341e-4fe5-83ac-e6e2bd5f991e\user_PCNAME_2024-02-29.08_37_31.cobertura.xml
@viceice thanks for info. What version of .NET SDK you use?
@fhnaseer I suspect that that dotnet test test --no-build
is executing several tests projects and doing at the end attachments merging. Could you please check which version of merging is used here? I remember some old merging was dropping conditions.
my local system
> dotnet --info ─╯
.NET SDK:
Version: 8.0.200
Commit: 438cab6a9d
Workload version: 8.0.200-manifests.91505830
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.200\
.NET workloads installed:
There are no installed workloads to display.
Host:
Version: 8.0.2
Architecture: x64
Commit: 1381d5ebd2
.NET SDKs installed:
6.0.419 [C:\Program Files\dotnet\sdk]
7.0.406 [C:\Program Files\dotnet\sdk]
8.0.102 [C:\Program Files\dotnet\sdk]
8.0.200 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
Can't check CI right now, but can reproduce locally with above versions.
I've also Visual Studio 17.9.1 on my local machine and the corresponding build tools on CI.
@viceice thanks for reporting this. We will work on fixing it when using dotnet test. As workaround you could try to switch to use dotnet-coverage
tool during test run:
dotnet-coverage collect -s coverage.config "dotnet test test --no-build"
You would need also to remove runsettings file from csproj and convert it to coverage.config (main tag should be <Configuration>
).
my current workaround is to use dotnet coverage merge
to merge both reports, which can then imported to jenkins.
is there any other benefit to use dotnet coverage
over build-in ?
By using dotnet-coverage
you get better performance and always latest features.
Build-in tool is running coverage for each test project separately and then merges results. While dotnet-coverage is using 1 collection for all test projects and merging is not needed. It means that if same project is referenced in many test projects build-in needs to instrument it several times. External tool instruments just once. Also external tool targets .net6
and is more optimized.
ok, will give it a try when our infra is back running 🙈
neverless this bug should be fixed anyways 🙃
OK, dotnet-coverage works partly better. I now have totally missing lines in one report. they are condittional net8.0 only and can't be coverred by net48 of cause:
#if NETFRAMEWORK
// some full framework code
#else
// some dotnet core code
#endif
So the lines for the non-full framework are missing in the sp report.
@viceice Can you please tell version of dotnet-coverage
?
@viceice Can you please tell version of
dotnet-coverage
?
still same 17.9.0 as before
it's 17.10.3
I am looking at the Jenkins ticket. With the latest dotnet-coverage merge
it is working as expected, right?
@fhnaseer original issue (missing conditions) is not when merging is done by dotnet-coverage
. I think case here is when there is attachments processing (merging) done by TP/.NET SDK.
@viceice can you please list all versions of Microsoft.NET.Test.Sdk
for all projects?
it's same as already mentioned above. I'm using central versioning and lockfiles. I also verified before.
I'm running two comands on CI.
First running cheap tests in
./test
folder on a general jenkins node inside a docker windows 2022 container. There is a sln and some test projects.dotnet test test --no-build ... Passed! - Failed: 0, Passed: 680, Skipped: 14, Total: 694, Duration: 17 s - Proj.Test.dll (net8.0) Attachments: ~\proj\test\Proj.XY.Test\TestResults\c64ddcc7-72a7-45a8-aae4-32e5cafbb395\user_PCNAME_2024-02-29.08_36_39.cobertura.xml
This gives the first coverage file.
The second command runs on a native SharePoint server for CI (jenkins node) purposes. So we only run SharePoint tests here. There is a sln and one test projects.
dotnet test sp/test --no-build ... Passed! - Failed: 0, Passed: 680, Skipped: 14, Total: 694, Duration: 17 s - Proj.SP.Test.dll (net48) Attachments: ~\proj\sp\test\Proj.SP.Test\TestResults\5f49f3d0-341e-4fe5-83ac-e6e2bd5f991e\user_PCNAME_2024-02-29.08_37_31.cobertura.xml
@viceice Can you please run test on individual test projects (rather on solution level) and share coverage files generated per test project?
I can only provide parts of it. hopefully tomorrow.
I think the lines already mentioned are the interesting ones.
@viceice we believe what is happening is your case:
dotnet test test --no-build
you execute tests for several projects and our internal logic is generating coverage report for each project separately (with conditions, you don't even see those reports on output)To make sure that this is your scenario we need to get information about line 61 for all projects from point 1 (separately) and if this is the scenario we will not be able to fix it. The only way is to use dotnet-coverage
tool which has a little bit different architecture and is able to merge all conditions as it contains additional information during merge.
<lines>
<line number="15" hits="1" branch="False" />
<line number="21" hits="1" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="1" branch="False" />
<line number="28" hits="1" branch="False" />
<line number="29" hits="1" branch="False" />
<line number="30" hits="1" branch="False" />
<line number="31" hits="1" branch="False" />
<line number="32" hits="1" branch="False" />
<line number="33" hits="1" branch="False" />
<line number="34" hits="1" branch="False" />
<line number="37" hits="1" branch="False" />
<line number="38" hits="1" branch="True" />
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="1" branch="False" />
<line number="45" hits="1" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
<condition number="1" type="jump" coverage="100%" />
</conditions>
</line>
<line number="46" hits="1" branch="False" />
<line number="47" hits="1" branch="False" />
<line number="48" hits="1" branch="False" />
<line number="50" hits="1" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
</conditions>
</line>
<line number="51" hits="1" branch="False" />
<line number="52" hits="1" branch="False" />
<line number="54" hits="1" branch="False" />
<line number="55" hits="1" branch="True" />
<line number="56" hits="1" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="1" branch="True" />
<line number="62" hits="1" branch="False" />
<line number="63" hits="1" branch="False" />
<line number="64" hits="1" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="1" branch="False" />
<line number="71" hits="1" branch="False" />
<line number="73" hits="1" branch="False" />
</lines>
<lines>
<line number="15" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="0" branch="False" />
<line number="28" hits="0" branch="False" />
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
<line number="32" hits="0" branch="False" />
<line number="33" hits="0" branch="False" />
<line number="34" hits="0" branch="False" />
<line number="37" hits="0" branch="False" />
<line number="38" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="0" branch="False" />
<line number="45" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="46" hits="0" branch="False" />
<line number="47" hits="0" branch="False" />
<line number="48" hits="0" branch="False" />
<line number="50" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="51" hits="0" branch="False" />
<line number="52" hits="0" branch="False" />
<line number="54" hits="0" branch="False" />
<line number="55" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="56" hits="0" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="62" hits="0" branch="False" />
<line number="63" hits="0" branch="False" />
<line number="64" hits="0" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="0" branch="False" />
<line number="71" hits="0" branch="False" />
<line number="73" hits="0" branch="False" />
</lines>
<lines>
<line number="15" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="0" branch="False" />
<line number="28" hits="0" branch="False" />
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
<line number="32" hits="0" branch="False" />
<line number="33" hits="0" branch="False" />
<line number="34" hits="0" branch="False" />
<line number="37" hits="0" branch="False" />
<line number="38" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="0" branch="False" />
<line number="45" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="46" hits="0" branch="False" />
<line number="47" hits="0" branch="False" />
<line number="48" hits="0" branch="False" />
<line number="50" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="51" hits="0" branch="False" />
<line number="52" hits="0" branch="False" />
<line number="54" hits="0" branch="False" />
<line number="55" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="56" hits="0" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="62" hits="0" branch="False" />
<line number="63" hits="0" branch="False" />
<line number="64" hits="0" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="0" branch="False" />
<line number="71" hits="0" branch="False" />
<line number="73" hits="0" branch="False" />
</lines>
<lines>
<line number="15" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="0" branch="False" />
<line number="28" hits="0" branch="False" />
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
<line number="32" hits="0" branch="False" />
<line number="33" hits="0" branch="False" />
<line number="34" hits="0" branch="False" />
<line number="37" hits="0" branch="False" />
<line number="38" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="0" branch="False" />
<line number="45" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="46" hits="0" branch="False" />
<line number="47" hits="0" branch="False" />
<line number="48" hits="0" branch="False" />
<line number="50" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="51" hits="0" branch="False" />
<line number="52" hits="0" branch="False" />
<line number="54" hits="0" branch="False" />
<line number="55" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
</conditions>
</line>
<line number="56" hits="0" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="0" branch="True" condition-coverage="0% (0/4)">
<conditions>
<condition number="0" type="jump" coverage="0%" />
<condition number="1" type="jump" coverage="0%" />
</conditions>
</line>
<line number="62" hits="0" branch="False" />
<line number="63" hits="0" branch="False" />
<line number="64" hits="0" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="0" branch="False" />
<line number="71" hits="0" branch="False" />
<line number="73" hits="0" branch="False" />
</lines>
Only project a fully covers the line 61 (see code in issue description)
Is project a single test project or solution? Could you please provide diagnostic logs from project a? https://github.com/microsoft/vstest/blob/main/docs/troubleshooting.md#collect-logs-and-crash-dump
Is project a single test project or solution? Could you please provide diagnostic logs from project a?
Yes, there are 4 test projects, but they depend on each other (tree)
https://github.com/microsoft/vstest/blob/main/docs/troubleshooting.md#collect-logs-and-crash-dump Will try todo when i've some time. Will there be our private source code inside those dumps?
You can skip dumps. Enough for us is: --diag:log.txt
wait, that project build's for net8.0 and net48. so probably another coverage result merge happens?
now running for both frameworks seperately.
<lines>
<line number="15" hits="1" branch="False" />
<line number="21" hits="1" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="1" branch="False" />
<line number="28" hits="1" branch="False" />
<line number="29" hits="1" branch="False" />
<line number="30" hits="1" branch="False" />
<line number="31" hits="1" branch="False" />
<line number="32" hits="1" branch="False" />
<line number="33" hits="1" branch="False" />
<line number="34" hits="1" branch="False" />
<line number="37" hits="1" branch="False" />
<line number="38" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
</conditions>
</line>
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="1" branch="False" />
<line number="45" hits="1" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
<condition number="1" type="jump" coverage="100%" />
</conditions>
</line>
<line number="46" hits="1" branch="False" />
<line number="47" hits="1" branch="False" />
<line number="48" hits="1" branch="False" />
<line number="50" hits="1" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
</conditions>
</line>
<line number="51" hits="1" branch="False" />
<line number="52" hits="1" branch="False" />
<line number="54" hits="1" branch="False" />
<line number="55" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
</conditions>
</line>
<line number="56" hits="1" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="1" branch="True" condition-coverage="50% (2/4)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
<condition number="1" type="jump" coverage="50%" />
</conditions>
</line>
<line number="62" hits="1" branch="False" />
<line number="63" hits="1" branch="False" />
<line number="64" hits="1" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="1" branch="False" />
<line number="71" hits="1" branch="False" />
<line number="73" hits="1" branch="False" />
</lines>
<lines>
<line number="15" hits="1" branch="False" />
<line number="21" hits="1" branch="False" />
<line number="23" hits="0" branch="False" />
<line number="25" hits="0" branch="False" />
<line number="26" hits="1" branch="False" />
<line number="28" hits="1" branch="False" />
<line number="29" hits="1" branch="False" />
<line number="30" hits="1" branch="False" />
<line number="31" hits="1" branch="False" />
<line number="32" hits="1" branch="False" />
<line number="33" hits="1" branch="False" />
<line number="34" hits="1" branch="False" />
<line number="37" hits="1" branch="False" />
<line number="38" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
</conditions>
</line>
<line number="39" hits="0" branch="False" />
<line number="40" hits="0" branch="False" />
<line number="41" hits="0" branch="False" />
<line number="44" hits="1" branch="False" />
<line number="45" hits="1" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
<condition number="1" type="jump" coverage="100%" />
</conditions>
</line>
<line number="46" hits="1" branch="False" />
<line number="47" hits="1" branch="False" />
<line number="48" hits="1" branch="False" />
<line number="50" hits="1" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="0" type="jump" coverage="100%" />
</conditions>
</line>
<line number="51" hits="1" branch="False" />
<line number="52" hits="1" branch="False" />
<line number="54" hits="1" branch="False" />
<line number="55" hits="1" branch="True" condition-coverage="50% (1/2)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
</conditions>
</line>
<line number="56" hits="1" branch="False" />
<line number="58" hits="0" branch="False" />
<line number="59" hits="0" branch="False" />
<line number="61" hits="1" branch="True" condition-coverage="50% (2/4)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
<condition number="1" type="jump" coverage="50%" />
</conditions>
</line>
<line number="62" hits="1" branch="False" />
<line number="63" hits="1" branch="False" />
<line number="64" hits="1" branch="False" />
<line number="67" hits="0" branch="False" />
<line number="68" hits="0" branch="False" />
<line number="69" hits="1" branch="False" />
<line number="71" hits="1" branch="False" />
<line number="73" hits="1" branch="False" />
</lines>
So it seems it's again the wrong merge when running both framework tests once 🤔
Unfortunately this can't be fixed because:
<line number="61" hits="1" branch="True" condition-coverage="50% (2/4)">
<conditions>
<condition number="0" type="jump" coverage="50%" />
<condition number="1" type="jump" coverage="50%" />
</conditions>
</line>
means line has 2 conditions and for each one case is covered. We are not able to calculate correct merge result (we don't know which part of condition was really covered) so we decide to remove conditions (similar to ReportGenerator). It is limitation of cobertura format.
50% + 50% could be merged to 50% or 100%.
The only workaround is to use dotnet-coverage collect
to execute all your tests. In this scenario we keep internally additional data (which exactly part of condition was covered) and we are able to perform full merge.
Thanks, i already use dotnet-coverage collect
now on ci runs and the normal collector inside visual studio to see coverage there (Fine Code Coverage
plugin).
Unfortunately this can't be fixed because:
<line number="61" hits="1" branch="True" condition-coverage="50% (2/4)"> <conditions> <condition number="0" type="jump" coverage="50%" /> <condition number="1" type="jump" coverage="50%" /> </conditions> </line>
means line has 2 conditions and for each one case is covered. We are not able to calculate correct merge result (we don't know which part of condition was really covered) so we decide to remove conditions (similar to ReportGenerator). It is limitation of cobertura format.
50% + 50% could be merged to 50% or 100%.
The only workaround is to use
dotnet-coverage collect
to execute all your tests. In this scenario we keep internally additional data (which exactly part of condition was covered) and we are able to perform full merge.
I understand that this is a limitation of the cobertura report format (or more precisely this is a problem of all reports, the actual coverage can only be computed with the execution data).
Despite of this architectural problem I think it would be better if you change the output in such cases. Your current output is brach=true
without a condition-coverage
. That means that the condition coverage will be automatically set to 100% (see DTD). I think it would be better to set in this case also the condition-coverage="100% (4/4)
explicitly. Then other tools can report at least the correct number of branches (if covered or not is undefined, so the <conditions>
can be skipped. (Another option would be to use the minimum coverage, so 50%)
<DataCollectionRunSettings> <DataCollectors> <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0"> <Configuration> <Format>Cobertura</Format> <CodeCoverage> <ModulePaths> <!-- Disable native instrumentation, causes SharePoint debug issues --> <EnableStaticNativeInstrumentation>False</EnableStaticNativeInstrumentation> <EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation> </ModulePaths> [...] </CodeCoverage> </Configuration> </DataCollector> </DataCollectors> </DataCollectionRunSettings>
@viceice Just a heads up. Are you sure <EnableStaticNativeInstrumentation>
and <EnableDynamicNativeInstrumentation>
should be under the node <ModulePaths>
? Shouldn't it be one level up, under <CodeCoverage>
according to these docs?
no, was a typo and already moved to correct place
I have two test projects which are running on seperate ci nodes because of different requirements. So i get two coverage files which i like to import in jenkins reports.
The code:
Project
a
, which fully covers that line gives:Project
b
doesn't cover that line (which is expected) and gives:Both reports should be identical beside coverage values.