OpenCover / opencover

A code coverage tool for .NET 2 and above (WINDOWS OS only), support for 32 and 64 processes with both branch and sequence points
https://blog.many-monkeys.com
Other
1.31k stars 248 forks source link

emit TeamCity summary messages #651

Open Trass3r opened 7 years ago

Trass3r commented 7 years ago

Would be nice. Maybe only enabled with a --teamcity cmdline option, like in NUnit.

quick hack that works:

 main/OpenCover.Console/Program.cs | 37 +++++++++++++++++++++++++++----------
 1 file changed, 14 insertions(+), 1 deletions(-)

diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs
index 238b006..f2b19d3 100644
--- a/main/OpenCover.Console/Program.cs
+++ b/main/OpenCover.Console/Program.cs
@@ -435,16 +435,33 @@ namespace OpenCover.Console
                 }
             }

-            if (coverageSession.Summary.NumClasses > 0)
+            var summary = coverageSession.Summary;
+            if (summary.NumClasses > 0)
             {
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsCTotal' value='{0}']", summary.NumClasses);
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsCCovered' value='{0}']", summary.VisitedClasses);
+
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsMTotal' value='{0}']", summary.NumMethods);
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsMCovered' value='{0}']", summary.VisitedMethods);
+
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsSTotal' value='{0}']", summary.NumSequencePoints);
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsSCovered' value='{0}']", summary.VisitedSequencePoints);
+
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsBTotal' value='{0}']", summary.NumBranchPoints);
+                logger.InfoFormat("##teamcity[buildStatisticValue key='CodeCoverageAbsBCovered' value='{0}']", summary.VisitedBranchPoints);
+
                logger.InfoFormat("Visited Classes {0} of {1} ({2})", coverageSession.Summary.VisitedClasses,
                                  coverageSession.Summary.NumClasses, Math.Round(coverageSession.Summary.VisitedClasses * 100.0 / coverageSession.Summary.NumClasses, 2));
                logger.InfoFormat("Visited Methods {0} of {1} ({2})", coverageSession.Summary.VisitedMethods,
sawilde commented 7 years ago

What information would you want to emit and why is it important to emit them as teamcity messages?

Could you not instead have a tool that parses the XML and emits the messages you require?

Trass3r commented 7 years ago

This guy tried parsing the xml but ended up parsing the stdout summary instead.

Unfortunately OpenCover xml reports aren't supported by TC. Only dotCover, NCover etc.

sawilde commented 7 years ago

I see - these are the docs for reference purposes - http://confluence.jetbrains.com/display/TCD10/Custom+Chart#CustomChart-DefaultStatisticsValuesProvidedbyTeamCity

Sam13 commented 7 years ago

There is also a NuGet package to generate TeamCity service messages: https://www.nuget.org/packages/TeamCity.ServiceMessages/

SteveGilham commented 7 years ago

Parsing the XML for the same numbers that are being emitted to stdout is trivial; the more so when you realise that only the 3rd line of the file, the one with the summary record, is of interest, and so you don't need to read in the however many megabytes of report. I have no idea what led the linked blogger to think that the numbers he was getting from stdout were any different from those in the XML <summary> tag, though the talk about line vs statement coverage seems to indicate a degree of confusion about what is being reported.

Making the entirely plausible assumption that this is happening on Windows, the PowerShell needed, which can be added as a build step, is as follows, most of which is writing the data

param([string] $path) # Path to the OpenCover XML log
$x = [xml](Get-Content $path -TotalCount 3 | Select-Object -Last 1)

Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsCTotal' value='$x.Summary.numClasses']"
Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsCCovered' value='$x.Summary.visitedClasses']"

Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsMTotal' value='$x.Summary.numMethods']"
Write-Host"##teamcity[buildStatisticValue key='CodeCoverageAbsMCovered' value='$x.Summary.visitedMethods']"

Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsSTotal' value='$x.Summary.numSequencePoints']"
Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsSCovered' value='$x.Summary.visitedSequencePoints']"

Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsBTotal' value='$x.Summary.numBranchPoints']"
Write-Host "##teamcity[buildStatisticValue key='CodeCoverageAbsBCovered' value='$x.summary.VisitedBranchPoints']"

though in real life, I XSLT the data to NCover format to feed into other report tooling that was developed back in the 1.5x days, and the TeamCity integration just comes for free.

SteveGilham commented 7 years ago

I did the experiment based on the above, and I found that

  1. It was better to locate the summary line by wildcard match amongst the first few than by number
  2. If you're embedding the PowerShell in the YAML, then you need to escape in the single quotes
  3. ADDED : "B" for block shows up on the build summary, "R" for branch doesn't

Other than that, It Just Worked.