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

Protocol method placeholders marked as untested #1616

Closed
andrewlalis opened this issue May 1, 2023 · 12 comments
Closed

Protocol method placeholders marked as untested #1616

andrewlalis opened this issue May 1, 2023 · 12 comments
Labels
bug Something isn't working

Comments

@andrewlalis
Copy link

Originally posted in pytest-cov as issue 593

Describe the bug
When computing the coverage of a project, I am getting cases where the placeholder body of a protocol method is considered as untested code. I would expect that the body of protocol methods would not be marked as untested.

To Reproduce
Consider the following python code:

from typing import Protocol

class Example(Protocol):
    def do_something() -> None:
        ...

Using:

  • Python version 3.11
  • pytest version 7.3.0
  • pytest-cov version 4.0.0
  • coverage version 7.2.2

Running coverage on a project containing the above Example protocol will produce a report indicating that the line containing the ... placeholder is untested. I believe that this is incorrect, as it is impossible and useless to test the existence of a placeholder statement in a protocol's method definition.

Expected behavior
I would expect coverage to omit marking the lines in the above code snippet as untested.

Additional context
PEP 544 - Protocols

@andrewlalis andrewlalis added bug Something isn't working needs triage labels May 1, 2023
@nedbat
Copy link
Owner

nedbat commented May 1, 2023

I see what you mean that these lines can't be executed. But I'm not sure how coverage.py could know that? You can exclude lines from coverage measurement with the exclude_also configuration setting.

@RonnyPfannschmidt
Copy link

@nedbat perhaps a recommended pre commit hook that adds those functions / lines would be of help (or a helper to dummy invoke them in testsuites)

@nedbat
Copy link
Owner

nedbat commented May 7, 2023

There are other issues about coverage.py not understanding various typing constructs:

So perhaps it is time to add some typing patterns to the default exclude patterns.

As an experiment, does this work to exclude the Protocols in your project?

[report]
exclude_also = 
    class \w+\(Protocol\):

@RonnyPfannschmidt
Copy link

Note that protocol abc classes ought not to be excluded as they sometimes implement default implementations of

@nedbat
Copy link
Owner

nedbat commented May 7, 2023

(your comment is a bit truncated, but:) Can you show a small sample of code that shouldn't be excluded? This is the risk of a simplistic method like regexes for deciding things about code.

@RonnyPfannschmidt
Copy link

I believe a fair set would be methods whose body is only the ellipsis

@nedbat
Copy link
Owner

nedbat commented May 7, 2023

I believe a fair set would be methods whose body is only the ellipsis

Unfortunately, I think that's not possible to express with a line-based regex. Is there a way to extend the power without becoming a full-fledged AST pattern matcher?

@nedbat
Copy link
Owner

nedbat commented May 7, 2023

BTW, links to real-world examples of tricky Protocols would be helpful.

@RonnyPfannschmidt
Copy link

@nedbat i believe that a reasonable hackish approximation would be to just consider lines with only a ellipsis covered

@Julian
Copy link

Julian commented May 23, 2023

It's slightly unfortunate to me that black or whatever other linters want the ... treated like a normal function body (and put on their own line), otherwise I think even "better" would be to limit this to :.*\.\.\.$ and to encourage method bodies to not have their own line for Protocols.

But given they do indeed put the ellipsis on their own line I guess I too agree it's probably most reasonable at the minute to do ^^.

@RonnyPfannschmidt
Copy link

@nedbat would it be sensible to ignore all single lines that contain only an ellipsis? i vaugely recall that function definitions get covered at definition time, so the ellipsis should be the only missing covered item

Julian added a commit to python-jsonschema/jsonschema that referenced this issue May 23, 2023
Mr-Pepe added a commit to vorausrobotik/voraus-python-template that referenced this issue Oct 25, 2023
Ignores `...` placeholders
(nedbat/coveragepy#1616).
Ignores `if TYPE_CHECKING:` because it can never be true at runtime
(nedbat/coveragepy#831).
Ignores branch coverage for `if not TYPE_CHECKING:` because it is always
true at runtime (nedbat/coveragepy#831).
g3n35i5 pushed a commit to vorausrobotik/voraus-python-template that referenced this issue Oct 25, 2023
Ignores `...` placeholders
(nedbat/coveragepy#1616).
Ignores `if TYPE_CHECKING:` because it can never be true at runtime
(nedbat/coveragepy#831).
Ignores branch coverage for `if not TYPE_CHECKING:` because it is always
true at runtime (nedbat/coveragepy#831).
@andrewlalis andrewlalis closed this as not planned Won't fix, can't repro, duplicate, stale Dec 27, 2023
@Julian
Copy link

Julian commented Jan 29, 2024

Color me ... well not shocked but certainly pleasantly surprised that

It's slightly unfortunate to me that black or whatever other linters want the ... treated like a normal function body

is now "fixed" / "improved" in Black 24 via psf/black#1797.

I'm not sure if this was closed because @nedbat WONTFIXed it (obviously all good if so) or if @andrewlalis you just closed it yourself because it was remaining open. But perhaps it's worth another consideration in light of the formatter change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants