8000 Report on *covered* not *uncovered* · Issue #507 · gcovr/gcovr · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Report on *covered* not *uncovered* #507

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 sen 8000 d you account related emails.

Already on GitHub? Sign in to your account

Closed
aytey opened this issue Aug 3, 2021 · 8 comments · Fixed by #836
Closed

Report on *covered* not *uncovered* #507

aytey opened this issue Aug 3, 2021 · 8 comments · Fixed by #836

Comments

@aytey
Copy link
aytey commented Aug 3, 2021

Is your feature request related to a problem? Please describe.

I am currently generating a report using gcovr -r . -s, which reports on all files and uncovered "entities" (where "entities" might be lines, might be branches).

It would be "useful" to me if this report was "reversed" and it only reported on covered files and covered entities.

Describe the solution you'd like

A flag to gcovr that was something like --covered and --uncovered (the default, which gives what we have today).

We might also need a --skip-empty to not report on files with no covered entities.

Describe alternatives you've considered

To "keep me moving", I've already implemented a change in FileCoverage.uncovered_lines_str (which is not the right change!), but which calculates the set uncovered_lines using line.is_covered vs. line.is_uncovered (which is what is there today).

This does not remove listing files that are totally uncovered, but just having only the covered entities is really helpful for me.

I could also do this myself using the json report but I generate a lot of reports, and the ~17 MiB per file is "too much" for me, and it also doesn't allow me to see things at the high-level (which the --status report does).

Additional context

(none)

@Spacetown
Copy link
Member

It would be "useful" to me if this report was "reversed" and it only reported on covered files and covered entities.

This is difficult because if you test the coverage the uncovered parts are the interested ones.

We might also need a --skip-empty to not report on files with no covered entities.

This is dangerous, e.g. a file with a bad coverage is by a error in the unittest now uncovered and therefore removed from the report. Now your coverage is increased because of less tests, this isn't what you want.

I could also do this myself using the json report but I generate a lot of reports, and the ~17 MiB per file is "too much" for me, and it also doesn't allow me to see things at the high-level (which the --status report does).

I think for this special use case it makes more sense to patch the json files and merge them together to get the status you want.

@aytey
Copy link
Author
aytey commented Aug 3, 2021

This is dangerous, e.g. a file with a bad coverage is by a error in the unittest now uncovered and therefore removed from the report. Now your coverage is increased because of less tests, this isn't what you want.

Sorry, this is a "unintended" side effect: I still want the totals to show the overall covered/uncovered; I just want the reports to list what was hit not what wasn't hit.

This is useful, for example, if I'm refactoring unit tests and want to make sure I'm still hitting what I hit before; or if I want to be able to say "okay, this line was exercised by which tests" (I have per-test gcovr reports, so finding out what hit what is easy, but only if I have "covered" not "uncovered").

I think for this special use case it makes more sense to patch the json files and merge them together to get the status you want.

Yeah, this is 100% possible with post-processing the json files -- however, the status report is so close with just flipping line.is_covered vs. line.is_uncovered that I thought it was worth raising the idea here.

@latk
Copy link
Member
latk commented Aug 3, 2021

Yeah, this is 100% possible with post-processing the json files -- however, the status report is so close with just flipping line.is_covered vs. line.is_uncovered that I thought it was worth raising the idea here.

This feature request is absolutely worth considering. I hadn't thought about this use case previously, but it clearly has some value.

The question is: enough value to include it in gcovr? This isn't just a few lines of changes, this requires documentation, testing, command line options, and keeping track of interactions between different configuration options (it's bad enough that the text report has separate line/branch modes). “No is temporary, yes is forever”, so I'm hesitant about features with limited value.

This is why the JSON format is great: it provides access to the full coverage data and allows new reports to be prototyped outside of gcovr. For example, the following script might be close to what you want. You can directly pipe the gcovr output into it (gcovr ... --json | ./show-covered.py), so you don't have to write large files to disk.

#!/usr/bin/python3
# SPDX-License-Identifier: CC0-1.0

import sys
import json
from gcovr.coverage import _find_consecutive_ranges  # yolo, no API stability guarantee
from packaging import version


def main():
    data = json.load(sys.stdin)

    json_version = version.parse(str(data['gcovr/format_version']))
    assert version.parse('0.1') <= json_version <= version.parse('0.2'), \
        f"possibly unsupported format version {json_version}"

    for file in data['files']:
        code_lines = [line for line in file['lines'] if not line['gcovr/noncode']]
        covered = [line['line_number'] for line in code_lines if line['count']]

        # only show files with coverage
        if not covered:
            continue

        n_covered = len(covered)
        n_total = len(code_lines)
        percent = n_covered / n_total * 100
        combined_line_ranges = ",".join(
            str(first) if first == last else f"{first}-{last}"
            for first, last in _find_consecutive_ranges(covered))

        print(file['file'])
        print(f"\t{percent:.2f}% lines covered ({n_covered} of {n_total})")
        print(f"\tlines: {combined_line_ranges}")


if __name__ == '__main__':
    main()

Example output:

main.cpp
        77.78% lines covered (7 of 9)
        lines: 4-5,8,13-14,18,25

But the use case of refactoring unit tests might instead benefit from a tool that directly compares different coverage runs and highlights the changes. So far, there is no such tool for gcovr (though it could be built upon the JSON report). I have no idea though how that could be visualized well. Thoughts about coverage diffs?

@Spacetown
Copy link
Member

This is useful, for example, if I'm refactoring unit tests and want to make sure I'm still hitting what I hit before; or if I want to be able to say "okay, this line was exercised by which tests" (I have per-test gcovr reports, so finding out what hit what is easy, but only if I have "covered" not "uncovered").

Ok, if you compare the result than this can be useful. Without a compare it is dangerous.

@latk A separate tool based on the JSON is a good idea. Another solution can be a option --reference=old.json and mark the differences in the output files where possible. E.g. in the (detailed) HTML report like it's done on codecov.io, in the text report and in the JSON format.

@aytey
Copy link
Author
aytey commented Aug 3, 2021

@latk @Spacetown thanks both for the insightful comments here.

Just so we're all on same page: this isn't "make or break" for me, and given I also maintain other open-source stuff, I fully appreciate that adding a "random, barely used" feature is a recipe for disaster.

Another solution can be a option --reference=old.json and mark the differences in the output files where possible

So, that works well in one regard, but not with "which coverage report exercised Line 345?" -- but it can be done with the json report with a little bit more work by me.

This is why the JSON format is great: it provides access to the full coverage data and allows new reports to be prototyped outside of gcovr

Given what you've both said so far, I honestly think me "home rolling" something to post-process the json report might be best.

As a quick query: have you compared the speed of the status report vs. the full-up json report? Anecdotally, I feel the status report is quicker to generate, but maybe it just feels that way because there's less to write to write to disk!

If either of you want to go ahead with this, and you want someone to volunteer to do the work, then I'm happy to give it ago. However, if you both say "the headache isn't worth the gain", then I'm totally fine with this being closed :)

@Spacetown
Copy link
Member

I've no measurements but the main time is used to run gcov and parse the output files. The output files are only a transformation of the internal data represenation into the output format.

@andrewvaughanj Please check @latk code snippet and adapt it for your needs. If you have a solutioon which fits your needs we can use this to implement an additional output format. But before implementing this I wan't to finish #474.

@Spacetown
Copy link
Member

@aytey Have you done something in this direction?

@aytey
Copy link
Author
aytey commented Sep 27, 2023

@Spacetown: all I had was my local changes that I highlighted in my original post.

I tried to find any VMs/clones/etc. of gcovr I had knocking around so I could share my complete changes with you, but I don't even have those.

What's even worse is I can't remember what I was using gcovr for or why I wanted this "inverted" report.

Basically, I'm afraid I'm of no use to you :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants
0