Skip to content
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

Adding Branch Coverage to API #1888

Closed
eleanorjboyd opened this issue Nov 5, 2024 · 6 comments
Closed

Adding Branch Coverage to API #1888

eleanorjboyd opened this issue Nov 5, 2024 · 6 comments
Labels
enhancement New feature or request fixed

Comments

@eleanorjboyd
Copy link

eleanorjboyd commented Nov 5, 2024

Hi! Eleanor from the Python for VS Code extension following up on API updates I was hoping to get which the VS Code python extension needs to support branch coverage! As you know, right now there is no way to get branch coverage from the API so Im looking to implement this but wanted to start the discussion as an issue to make sure I have the right approach.

What I think is the easiest access point to the branch coverage values I am looking for is in the Analysis class. Here there is the function _total_branches() which would provide one value I need and then I would need either covered branches or missing branches. n_missing_branches is defined in the Analysis class but not accessible, so maybe a getter for this value would be sufficient. (it is my understanding that branches are different from arcs and therefore it is not sufficient to display arc values but if I am mistaken please let me know)

Next is getting the Analysis class instance for a given file. From what I can tell, it seems like this is returned in two places, _analyze or analysis_from_file_reporter, (which makes sense given that _analyze calls analysis_from_file_reporter). It seems like _analyze under the Coverage class is probably easiest, given the comment "Private for now." in its docstring this might have been something already considered.

To summarize, what I am suggesting is:

  1. making the Analysis class part of the API
  2. adding the _analyze function in Coverage to the API
  3. adding a function to Analysis to surface either covered branches or missing branches

These are quite a few asks so if you have a suggestion that might add less to the API (and less to maintain) please let me know. It is not my intent to bloat the API only get these branch numbers so we could also attempt edits to surface them without the Analysis data class but I am unsure.

For context, here is where we collect and transform coverage in the extension. Here was my previous idea on how to get branch coverage before I realized it was not part of the API.

Thank you!

@nedbat
Copy link
Owner

nedbat commented Feb 16, 2025

After thinking about this, I don't think I want to make Analysis public. It's a bit low-tech, but I think I'd rather add another public method: Coverage.branch_analysis that returns the branch information needed. That would work for you, yes?

@eleanorjboyd
Copy link
Author

Yes that would be great! Happy to make changes in the PR to switch to this or follow your lead if you want to design the API surface yourself. Thanks!

@nedbat
Copy link
Owner

nedbat commented Feb 21, 2025

I guess we'll see who gets to it first. I'm not sure exactly what data you need.

@nedbat
Copy link
Owner

nedbat commented Mar 16, 2025

Looking at the pull request, it seems like branch_stats is what you want. We can add this to the Coverage class:

diff --git a/coverage/control.py b/coverage/control.py
index 70ecb833..1fbe03bc 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -960,6 +960,20 @@ def _analyze(self, morf: TMorf) -> Analysis:
         filename = self._file_mapper(file_reporter.filename)
         return analysis_from_file_reporter(data, self.config.precision, file_reporter, filename)

+    def branch_analysis(self, morf: TMorf) -> dict[TLineNo, tuple[int, int]]:
+        """Get branch statistics about a module.
+
+        `morf` is a module or a file name.
+
+        Returns a dict mapping line numbers to a tuple:
+        (total_exits, taken_exits).
+
+        .. versionadded:: 7.7
+
+        """
+        analysis = self._analyze(morf)
+        return analysis.branch_stats()
+
     @functools.lru_cache(maxsize=1)
     def _get_file_reporter(self, morf: TMorf) -> FileReporter:
         """Get a FileReporter for a module or file name."""

nedbat added a commit that referenced this issue Mar 16, 2025
@nedbat
Copy link
Owner

nedbat commented Mar 16, 2025

I've added Coverage.branch_stats() in commit 33f12df.

@nedbat nedbat closed this as completed Mar 16, 2025
@nedbat nedbat added the fixed label Mar 16, 2025
@nedbat
Copy link
Owner

nedbat commented Mar 16, 2025

This is now released as part of coverage 7.7.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fixed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants