Skip to content

Console reporting even when saving to json file and other questions #56

@echoix

Description

@echoix

I'm trying to integrate slipcover instead of a coverage.py, as coverage.py takes an already too long 4*35 minutes without coverage (test suite split into 4 CI jobs), to about 45-50+ min without coverage.py.

With slipcover, the times taken are about the same as without coverage, so it's great.

I'll have a couple questions, as I did my best to understand how this tool works, as there isn't a documentation for the project yet, and I tried to follow the couple issues beforehand.

I've been able to upload to codecov, as long as I set the output file name to coverage.json (if it is called .coverage.json, codecov tries to call coverage.py to merge files as it looks like if it were multiple files created with the parallel option, since it is like the .coverage.* pattern).

So, knowing that there is a way to have a human, tabular report in slipcover, how is it possible to request it to be shown?
The relevant function I think is print_coverage located here

def print_coverage(coverage, *, outfile=sys.stdout, missing_width=None, skip_covered=False) -> None:
"""Prints coverage information for human consumption."""
from tabulate import tabulate
if not coverage.get('files', None): # includes empty coverage['files']
return
branch_coverage = coverage.get('meta', {}).get('branch_coverage', False)
def table():
for f, f_info in sorted(coverage['files'].items()):
exec_l = len(f_info['executed_lines'])
miss_l = len(f_info['missing_lines'])
if branch_coverage:
exec_b = len(f_info['executed_branches'])
miss_b = len(f_info['missing_branches'])
pct_b = 100*exec_b/(exec_b+miss_b) if (exec_b+miss_b) else 0
pct = f_info['summary']['percent_covered']
if skip_covered and pct == 100.0:
continue
yield [f, exec_l+miss_l, miss_l,
*([exec_b+miss_b, miss_b, round(pct_b)] if branch_coverage else []),
round(pct),
format_missing(f_info['missing_lines'], f_info['executed_lines'],
f_info['missing_branches'] if 'missing_branches' in f_info else [])]
if len(coverage['files']) > 1:
yield ['---'] + [''] * (6 if branch_coverage else 4)
s = coverage['summary']
if branch_coverage:
exec_b = s['covered_branches']
miss_b = s['missing_branches']
pct_b = 100*exec_b/(exec_b+miss_b) if (exec_b+miss_b) else 0
yield ['(summary)', s['covered_lines']+s['missing_lines'], s['missing_lines'],
*([exec_b+miss_b, miss_b, round(pct_b)] if branch_coverage else []),
round(s['percent_covered']), '']
print("", file=outfile)
headers = ["File", "#lines", "#l.miss",
*(["#br.", "#br.miss", "brCov%", "totCov%"] if branch_coverage else ["Cover%"]),
"Missing"]
maxcolwidths = [None] * (len(headers)-1) + [missing_width]
print(tabulate(table(), headers=headers, maxcolwidths=maxcolwidths), file=outfile)

Up to now, I wasn't able to see that it in action yet.

It might be related to the logic in the function printit inside atexit here:

def sci_atexit():
global output_tmpfile
def printit(coverage, outfile):
if args.json:
print(json.dumps(coverage, indent=(4 if args.pretty_print else None)), file=outfile)
else:
sc.print_coverage(coverage, outfile=outfile, skip_covered=args.skip_covered,
missing_width=args.missing_width)

  • If I understood correctly, on my first try, just replacing python interpreter by python -m slipcover ran some coverage, but didn't save any data of it, and didn't display anything too. (Hopefully I only ran a subset of the tests instead of 35 minutes ;) )
  • If I use python -m slipcover --json in order to have a file output (or as I thought it would), it only outputs a json to the terminal, it doesn't save it with a default name. There is still no file created that could be used to post-process what slipcover collected, either with slipcover or any custom-purpose tool.
  • If I use python -m slipcover --out coverage.json, then a json file is saved, but no terminal output. However, that file is empty (0 bytes).
  • If I use python -m slipcover --json --out coverage.json, then there is a file saved, no terminal output, and the file is valid, but didn't contain any files covered.
  • If I use python -m slipcover --json --out coverage.json --source ., then there is a file saved, no terminal output, and the file is valid, and contains some files, (with missing lines reported), but no lines covered (that's on my side, as the source should be better tuned with the paths like I needed with coverage.py)

Other questions, in no particular order

  • Does slipcover save the data collected somewhere?
  • Can slipcover work without specifying any --source argument, by only saving what is in under the current directory, a bit like other coverage tools?
  • Is slipcover's json output summarized? If not, and the complete data is there, it might be possible to use the couple functions in https://coverage.readthedocs.io/en/latest/api_coveragedata.html and be able to create a .coverage file just like coverage.py uses, and use coverage.py to use all their reporting facilities. For example, I already had to create a custom path mapping function since the mapping available from their config file worked on path prefixes, and I needed to change some file names too. https://github.com/OSGeo/grass/blob/b082d422ef215c21a0fcdaf3a0a5b38cc7c51ea1/utils/coverage_mapper.py Their format is now an SQLite database, and is quite simple to understand. If it's realistic, I could try to make the missing integration if you point me to what your data structures are equivalent to their arcs and lines. Maybe slipcover could be used as a tracer plugin even, to see...
  • Is there any mechanism to map paths back to files in the repo, like multiple other coverage tools (outside of Python, like dotnet and Java)? If not, creating a coverage.py file from the api as above would allow to use their mechanisms with a simple coverage combine or even directly with any of their reporting options.
  • Can the --source option be used multiple times, or it must be used once with comma separating the different paths?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions