New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Cobertura coverage format #2298
base: main
Are you sure you want to change the base?
Conversation
Also, it seems that the XML attributes don't always have consistent ordering when the XML is serialized. This is currently failing the tests. Does anyone know how we could get past this?
|
Thanks for looking into this so fast! :) |
After fixing all the build failures (related to multiple PS versions and OSs), I re-ran this branch to produce a Cobertura report against my other project and compared it to the HTML report I previously generated from the JaCoCo option. Everything seems to match up (whew!). |
@joeskeen just checked it, looks good to me! Again, thanks for your help and work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see comments below. As mentioned, I'm not an expert on coverage and haven't tested this format, so I might be wrong.
Still, it feels like line-elements are unnecessarily duplicated in the report and should only be reported once per method or class. Though it might work fine, it would cause large files
@fflaten thanks for the thorough review. I did some more testing yesterday and found that there were a lot of problems with my initial implementation. So yesterday I started from scratch and I'm liking it much better. I'll push the changes shortly after I address a couple linting issues. |
@fflaten (or others) - my last remaining linting error is
What is the suggested alternative for Edit: maybe this isn't an issue, I just found that |
Looks like using |
src/functions/Coverage.ps1
Outdated
| New-LineNode | ||
|
||
$lines = $allLines ` | ||
| & $SafeCommands["Where-Object"] $methodLineFilter ` |
Check notice
Code scanning / PSScriptAnalyzer
The built-in *-Object-cmdlets are slow compared to alternatives in .NET. To fix a violation of this rule, consider using an alterantive like `foreach`-keyword etc.`.
src/functions/Coverage.ps1
Outdated
$classLineFilter = { $_.File -eq $classGroup.Name -and -not $_.Function } | ||
|
||
$coveredLines = $CoverageReport.HitCommands ` | ||
| & $SafeCommands["Where-Object"] $classLineFilter ` |
Check notice
Code scanning / PSScriptAnalyzer
The built-in *-Object-cmdlets are slow compared to alternatives in .NET. To fix a violation of this rule, consider using an alterantive like `foreach`-keyword etc.`.
A replacement depends on each scenario, but often If you can avoid them, that's great, but it's not critical in this code as it's only executed once in post-process. The rule is there to highlight potential performance issues in the runtime for code executed 100s or 1000s of times. 🙂 Please let me know when it's ready for review again. |
Co-authored-by: Frode Flaten <3436158+fflaten@users.noreply.github.com>
@fflaten I think I've worked out all of the kinks as I was able to successfully use my branch of Pester in Azure Pipelines, generate a Cobertura report, and merge it with my existing JavaScript Cobertura report. All the numbers in the report are correct. You may proceed to review :) |
It seems that XML ordering has once again caused me issues in the tests. I'll have to sort methods by name to fix the output. |
Need to review tomorrow (hopefully), but immediately noticed some mismatches with the DTD.
|
@fflaten Yeah, I noticed those discrepancies as well. I will need to do further investigation as I mostly modeled this after the output of the |
I finally found the source for my JavaScript Cobertura reports, not in It seems that they use the DTD I'll switch the declaration to use that one once I figure out the correct reference URL for it. |
I tried just changing
So I think I'll go that route, as the current output is almost compliant with the |
Scratch that. We'll need to optimize this once it works as intended. # running a stopwatch around Get-JaCoCoReportXml/Get-CoberturaReportXml call in Main.ps1
$c = New-PesterConfiguration
$c.Run.Path = './tst/'
$c.Run.ExcludePath = '*/demo/*', '*/examples/*', '*/testProjects/*', '*/Pester.Tests.ps1'
$c.Output.Verbosity = 'None'
$c.CodeCoverage.Enabled = $true
$c.CodeCoverage.Path = './src/'
$c.CodeCoverage.UseBreakpoints = $false
$c.CodeCoverage.OutputFormat = 'JaCoCo'
$r = Invoke-Pester -Configuration $c
WARNING: CC took 00:00:13.0819358
$c.CodeCoverage.OutputFormat = 'Cobertura'
$r = Invoke-Pester -Configuration $c
WARNING: CC took 00:02:14.9018360 A profiler-run highlights line-filters. The durations are multiplied due to the profiler, but percent + hitcount is correct. So these don't scale well.
|
Thanks for looking into that. I'll rework those areas, perhaps by doing a single pass through the |
@fflaten would you be able to run the profiler again? |
Amazing improvements! The stopwatch test went down to 3s (!) 🏎️ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome job! 🎉
I haven't tested this in a report generator or CI, so if someone's able to try it out with Gitlab that would be great.
Would also like @nohwnd to take a quick look. Be aware that this won't be merged until he finds some time, so might take a little while.
} | ||
} | ||
|
||
$xmlDeclaration = '<?xml version="1.0" ?>' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include encoding="UTF-8"
like JaCoCo? Though I just noticed both hardcode this, while we actually make this configurable in CodeCoverage.OutputEncoding
😬
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting... so what should we do? Hard-code or try to get it from the settings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd hardcode for now to make sure it's compatible with Cobertura-tools. At least we'd be consistent and support unicode-characters properly.
Then we'll fix both later in a separate issue as it's more a xml-thing.
} | ||
|
||
$xmlDeclaration = '<?xml version="1.0" ?>' | ||
$docType = '<!DOCTYPE coverage SYSTEM "https://raw.githubusercontent.com/cobertura/cobertura/master/cobertura/src/site/htdocs/xml/coverage-loose.dtd">' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nohwnd: Should we point to this external URL or just coverage-loose.dtd
and include the DTD-file in our build like the other output formats? I'm not familiar with the history of that decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to do it whichever way is the preferred way. Would you like me to make that change or do we need to consult other maintainers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just a contributor, so lets wait on Jakub :)
$xmlDeclaration = '<?xml version="1.0" ?>' | ||
$docType = '<!DOCTYPE coverage SYSTEM "https://raw.githubusercontent.com/cobertura/cobertura/master/cobertura/src/site/htdocs/xml/coverage-loose.dtd">' | ||
$coverageXml = ConvertTo-XmlElement -Node $coverage | ||
$document = "$xmlDeclaration`n$docType`n$(([System.Xml.XmlElement]$coverageXml).OuterXml)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Is the cast necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... maybe not. I'll try without it.
PR Summary
Cobertura is a commonly used code coverage format, and has been requested as a feature: #2203
Fix #2203
To implement this feature, I copy-pasted the JaCoCo code and modified it to produce the required XML structure for Cobertura.
I am not an expert on the Cobertura format, but I did reference their DTD and the Cobertura output from my TypeScript project that uses
jest-junit
. If anyone is able to review it for correctness, I would greatly appreciate it. A good place to analyze the output is the unit test I added, where you can compare the JaCoCo output directly above it to the new Cobertura output (I used the same inputs for both reports).PR Checklist
Create Pull Request
to mark it as a draft. PR can be markedReady for review
when it's ready.