I’m available for freelance work. Let’s talk »

Try it: function/class coverage report

Monday 15 April 2024

I’ve added experimental function and class coverage reports to coverage.py. I’d like feedback about whether they behave the way you want them to.

I haven’t made a PyPI release. To try the new reports, install coverage from GitHub. Be sure to include the hash:

$ python3 -m pip install git+https://github.com/nedbat/coveragepy@f10c455b7c8fd26352de#egg=coverage==0.0

Then run coverage and make an HTML report as you usually do. You should have two new pages, not linked from the index page (yet). “htmlcov/function_index.html” is the function coverage report, and the classes are in “htmlcov/class_index.html”.

I had to decide how to categorize nested functions and classes. Inner functions are not counted as part of their outer functions. Classes consist of the executable lines in their methods, but not lines outside of methods, because those lines run on import. Each file has an entry in the function report for all of the lines outside of any function, called “(no function)”. The class report has “(no class)” entries for lines outside of any classes.

The result should be that every line is part of one function, or the “(no function)” entry, and every line is part of one class, or the “(no class)” entry. This is what made sense to me, but maybe there’s a compelling reason to do it differently.

The reports have a sortable column for the file name, and a sortable column for the function or class. Where functions or classes are nested, the name is a dotted sequence, but is sorted by only the last component. Just like the original file listing page, the new pages can be filtered to focus on areas of interest.

You can look at some sample reports:

It would be helpful if you could give me feedback on the original issue about some questions:

  • Is it useful to have “(no function)” and “(no class)” entries or is it just distracting pedantry? With the entries, the total is the same as the file report, but they don’t seem useful by themselves.
  • Does the handling of nested functions and classes make sense?
  • Should these reports be optional (requested with a switch) or always produced?
  • Is it reasonable to produce one page with every function? How large does a project have to get before that’s not feasible or useful?
  • And most importantly: do these reports help you understand how to improve your code?

This is only in the HTML report for now, but we can do more in the future. Other ideas about improvements are of course welcome. Thanks!

Comments

[gravatar]

Is it useful to have “(no function)” and “(no class)” entries or is it just distracting pedantry? With the entries, the total is the same as the file report, but they don’t seem useful by themselves.

Yes, I think those are useful to include because (when) they are part of the code total being counted.

My preference, though, would be to have them as the first entry for a given file. Because they are “top-level” code, at the entire-file level, so I’d expect to see them before any more specific item.

[gravatar]

Should these reports be optional (requested with a switch) or always produced?

Provided they have little impact on the space or time performance of the tool, I don’t see a reason not to have them generated by default as part of “generate the report” command.

[gravatar]

Is it reasonable to produce one page with every function? How large does a project have to get before that’s not feasible or useful?

I’m surprised to see “all classes / functions across all files, on one report page” at all.

Rather, I’d expect to “drill down” to each file’s separate page, to see the breakdown by function coverage and/or class coverage.

[gravatar]

And most importantly: do these reports help you understand how to improve your code?

Hell yes! Just like a performance report categorised by function and class, a coverage report categorised this way helps me more quickly assess what matters for future work to improve the code base.

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
Comment text is Markdown.