In our build, we’re producing 2 different lcov report: one for unit test and 1 for e2e tests and it
looks like SonarQube has some problems with branch coverage information
for example with this very simple code:
private getAnchorElement(link: RouterLink | string | undefined): HTMLElement | null {
const fragment = typeof link === 'string' ? link: link?.fragment;
return fragment ? this.navigationService.getAnchorElement(fragment) : null;
}
with 1 lcov report (unit test), the last line is fully covered by tests
with 2 lcov reports(unit test and e2e tests), the last line will be marked as "partially covered by tests (2 of 4 conditions)
To be clear, when you import the reports separately, the return line comes out partially covered?
For the reports merger, that’s no provided by us, so you’ll have to take that up with its maintainers. Or are you saying that the merger works fine, but our import of the merged report comes out weird?
Is the merged LCOV report correctly showing the last line as fully covered when you test it with https://lcov-viewer.netlify.app/?
If that is the case, can you please share the two reports (unit and e2e)? They should not contain sensitive information and should be small enough to be shareable.
Thanks @Xav, I merged what you shared with me using lcov-result-merger and the resulting coverage file is correct - at least, using https://lcov-viewer.netlify.app/, the merged coverage file showed that the source file is fully covered.
You said earlier that you tried this solution but it didn’t work. Can you give us more information about what didn’t work? Was SonarQube unable to interpret the merged file successfully?
Could you also share with us the non-sensitive scanner settings that you use?
That’s fine. I’ll try to reproduce the issue by the end of the week, with some merged LCOV reports. Hopefully, I can confirm the issue and move forward to fixing it.
I need one more information from you, not sensitive: can you give me the index of the line return fragment ? this.....getAnchorElement(fragment) : null;? I’m testing the merged coverage using an empty file - which works fine - and I just need to paste the wrongly covered line at the right position.
Also - and mostly - I’m concerned by the fact that the first LCOV report that you shared with me privately reports 22 branches while the second one reports 32 branches, for the same file.
I need one more information from you, not sensitive: can you give me the index of the line return fragment ? this.....getAnchorElement(fragment) : null; ?
It’s line 165.
Also - and mostly - I’m concerned by the fact that the first LCOV report that you shared with me privately reports 22 branches while the second one reports 32 branches, for the same file.
BRF:22
BRF:32
Can you please check that point?
I checked the BRF and I confirm it’s 22 on the first report and 32 in the second one
My theory is that Jest is using v8 coverage as the source of truth - which means that it gets the branch count from the lines that were actually hit during the execution flow, while IstanbulJS, which instruments the sources before executing them, is getting the branch count from the AST itself.
But before jumping to conclusions, if you agree, I’d like to propose a test to check the actual number of branches in the file, just to see which one of Jest or IstanbulJS is correct.
Would you agree to run one-double-zero locally on this specific file? You can actually have odz execute any command since we are just interested in the number of branches detected by the tool. I propose date, but really any command would work.
odz --sources=libs\com-widgets\src\lib\widget\nav_gation\nav_gation-renderer.component.ts --reporters=text-lcov date
(for some reason, I can’t put the word nav.i. on a comment, so I replaced it with nav_ in the above instruction)
This command should output to your terminal an LCOV report. We are interested in the BRF: value that is near the end.
I’ve been investigating deeper, and there is another thing that looks suspect.
In the unit test report, we see that, between line 176 and line 180, there is no line coverage, which means nothing relevant was hit (probably some empty lines or comments):
DA:176,0
DA:180,1
But in the e2e test report, there are relevant lines between 174 and 180:
DA:174,0
DA:179,0
DA:180,0
The same kind of discrepancies are found at the function level (there is a function at line 183 in the unit test report but none in the e2e test report; there is a function at line 199 of the e2e test report but none in the unit test report).
I’ve been trying to reproduce the issue that you encounter, using multiple LCOV reports generated by tests that hit different locations of the source files, and I was not able to find any issue: the coverage reported by SonarQube is always consistent with the LCOV reports.
I suspect that the LCOV reports that you shared with me are faulty - I mean, they look suspect. Would you mind double checking how they are generated, and if the issues that I mentioned make sense?