-
-
Notifications
You must be signed in to change notification settings - Fork 440
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
Uncovered branches are reported if generator iterators are not exhausted #1617
Comments
Actually, that doesn't make sense, given that it doesn't happen with |
Further, this reproduces with: val = next(iter((c for c in "abc")), None) but not with: val = next(iter([c for c in "abc"]), None) so I'm fairly convinced it's something about generator expressions... |
next
wrong
This is perhaps a minimal reproducer: (c for c in ())
pass That reports |
@nedbat helped me understand what's happening here, and it's much simpler than I was imagining. I wasn't correctly interpreting what the It's possible to provoke a similar report with list comprehensions - for instance, this test program: try:
[x / 0 for x in (1, 2, 3)]
except ZeroDivisionError:
pass reports Having gathered my thoughts a bit after my conversation with Ned, I think that this isn't a helpful thing for Coverage to report. Coverage doesn't complain about failures to exhaust other iterators, like But moreover, Coverage doesn't complain when you fail to exhaust other iterators that are functions. There's no missing branch reported if you call You might say "but that uncovered branch is inside the implementation of You might say "the difference is that the code running inside a generator expression is user-provided, not part of the interpreter's implementation like I'm pretty convinced that this report isn't useful to or actionable by users - what do you think, @nedbat? |
I don't often require 100% branch coverage, so I don't know that I have a strong opinion on this, but one point in favor of the "this is not useful" side might be the question of what happens when you have infinite iterators? Do you get the same kind of branch miss in this situation? a = (x.upper() for x in itertools.repeat("Spam"))
print("\n".join(itertools.islice(a, 0, 100))) Seems like you shouldn't, since exhausting On the other hand, if you have a situation like this: def my_func(n, a=(1, 2, 3.0, 4, "five")):
it = (int(x) for x in a)
return next(itertools.islice(it, n, n+1))
@pytest.mark.parameterize("n", [0, 1, 2, 3])
def test_my_func(n):
assert isinstance(my_func(n), int) It would be nice to recognize that you have missed the failing cases |
I thought about bringing infinite generators up, but Coverage already requires you to add a |
In an attempt to reach 100% coverage I broke out the various ways `reset_latestest_by_ip` could be called... to no avail. I believe this issue explains why the list comprehension shows a branch part as uncovered: - nedbat/coveragepy#1617
Describe the bug
Given this program as
test.py
:Branch coverage claims that there is an uncovered arc from line 2 (the
val = next(...)
) toexit
. As far as I can see, there is no branch there.To Reproduce
Interestingly, if you change line 2 to:
Coverage no longer believes there is an uncovered branch, despite the fact that
(c for c in "abc")
anditer("abc")
both return iterators over the same 3 elements.Expected behavior
There should not be a branch detected from line 2 to exit, as the only line that can follow 2 is 3. I suspect the issue may perhaps be that Coverage doesn't understand that 2-argument
next
will never raise aStopIteration
.Additional context
This may be the same issue as #605 (comment) - I started to add this as a comment there, but then thought I'd err on the side of a new issue.
The text was updated successfully, but these errors were encountered: